1. Spring Boot 高级
2. 自动配置
2.1. Condition
Condition是spring 4.0 增加的条件判断功能 通个这个功能可以实现选择性的创建Bean操作
启动类返回IOC容器 获取bean对象
//启动springboot的应用 返回spring的IOC容器ConfigurableApplicationContext context = SpringApplication.run(SpringbootProfilesApplication.class, args);//获取beanObject redisTemplate = context.getBean("redisTemplate");System.out.println(redisTemplate);
创建一个类实现 Condition接口 实现matches方法 返回一个布尔值 true为允许创建bean false为不允许
import org.springframework.context.annotation.Condition;import org.springframework.context.annotation.ConditionContext;import org.springframework.core.type.AnnotatedTypeMetadata;public class ClassCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {try {//获取指定的class 是否加载 没有则不允许创建新的beanClass<?> cls = Class.forName("redis.clients.jedis.Jedis");} catch (ClassNotFoundException e) {return false;}return true;}}
使用注解@Conditional
@Configurationpublic class UserConfig {@Bean//如果为true则创建该bean@Conditional(ClassCondition.class)public User user(){return new User();}}
2.2. 自定义Conditional注解
创建注解
package com.itheima.springbootprofiles.condtion;import org.springframework.context.annotation.Conditional;import java.lang.annotation.*;@Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documented@Conditional(ClassCondition.class)public @interface ConditionOnClass {String[] value();}
创建一个类实现 Condition接口 实现matches方法 返回一个布尔值 true为允许创建bean false为不允许
package com.itheima.springbootprofiles.condtion;import org.springframework.context.annotation.Condition;import org.springframework.context.annotation.ConditionContext;import org.springframework.core.type.AnnotatedTypeMetadata;import java.util.Map;public class ClassCondition implements Condition {/**** @param context 上下文对象 用于获取环境 ioc容器 classloader对象* @param metadata 注解元对象 可以用于获取注解定义的属性值* @return*/@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName()); //获取注解中的元数据String[] value = (String[]) map.get("value"); //获取value中值try {//获取指定的class 是否加载 没有则不允许创建新的beanfor (String classNmae : value) {Class<?> cls = Class.forName(classNmae);}} catch (ClassNotFoundException e) {return false;}return true;}}
使用注解
@Configurationpublic class UserConfig {@Bean// @Conditional(ClassCondition.class)@ConditionOnClass("com.alibaba.fastjson.Json")public User user(){return new User();}}
2.3. 常用条件注解
- @ConditionalOnProperty 判断配置文件中是否有对应属性和值才初始化Bean
- @ConditionalOnClass 判断环境中是否有对应的字节码文件才初始化Bean
- @ConditionalOnMissingBean 判断环境中没有对应的Bean时才初始化Bean
- @ConditionalOnBean 判断容器中有指定组件时才注册该被标注的组件
@Bean//当application配置文件中有此键值对时才创建此bean@ConditionalOnProperty(name = "name",havingValue = "zhangsan")public User user2(){return new User();}
@ConditionalOnBean(name = "tomcat")@Bean // 给容器注册添加组件 用bean声明 返回的值,就是组件在容器中的实例public User user01() {User zhangsan = new User("zhangsan",18);zhangsan.setPet(tomcatpet());return zhangsan;}
2.4. 切换内置web服务器
SpringBoot的web环境默认为tomcat作为内置服务器,Springboot提供了4种内置服务器让我们选择
- 排除tomcat 引入jetty依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!-- 排除tomcat--><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><!-- 引入jetty的依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jetty</artifactId></dependency>
2.5. @Enable* 注解
SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的,而底层原理是使用了@Import注解导入一些配置类,实现Bean的动态加载
2.5.1. 第三方包导入
在项目或者POM中添加坐标
Springboot并不会加载到我们自己手动导入的第三方包
- 使用@ComponentScan(“引用路径”) 重新定义扫描目录 SpringBoot默认为启动类的根路径下Bean
- 使用@Import(字节码) 导入第三方jar包
- 自定义注解 实现@Import 并继承其之前的注解 简化我们书写
2.5.2. @Import注解
@Enable*底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中,而@Import提供4种用法
导入Bean
导入配置类
导入ImportSelector实现类 一般用于加载配置文件中的类 ```java public class MyImportSelector implements ImportSelector { //实现selectImports方法 需要一个元数据 @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.itheima.domain.user"};
} }
//使用@Import导入实现类 @Import(MyImportSelector.class)
4.导入 ImportBeanDefinitionRegistrar 实现类```javapublic class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//Bean对象AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();//创建bean的名称 以及需要一个bean对象registry.registerBeanDefinition("user",beanDefinition);}}//使用@Import导入实现类@Import(MyImportBeanDefinitionRegistrar.class)
2.5.3. @EnableAutoConfiguration
- @EnableAutoConfiguration 注解内部使用@Import(AutoConfigurationImporttSelector.class) 来加载配置类
- 配置文件位置: META-INF/spring.factories 该配置文件中定义了大量的配置类 当SpringBoot应用启动时,会自动加载这些配置类 初始化Bean
- 并不是所有Bean都会被初始化 在配置类中使用Condition来加载满足条件的Bean
2.6. 自定义自动配置
配置redis 配置类
package com.itheima.redisspringbootautoconfigure.redis.config;import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "redis")public class RedisProperties {private String host="localhost";private int port =6379;public String getHost() {return host;}public void setHost(String host) {this.host = host;}public int getPort() {return port;}public void setPort(int port) {this.port = port;}}
自动配置类
package com.itheima.redisspringbootautoconfigure.redis.config;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import redis.clients.jedis.Jedis;@Configuration@EnableConfigurationProperties(RedisProperties.class)@ConditionalOnClass(Jedis.class)public class RedisAutoConfiguration {@Bean@ConditionalOnMissingBean(name = "jedis")public Jedis jedis(RedisProperties redisProperties) {return new Jedis(redisProperties.getHost(), redisProperties.getPort());}}
在resource 下创建META-INF目录 创建spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.itheima.redisspringbootautoconfigure.redis.config.RedisAutoConfiguration
- 使用 在项目pom中引入自定义自动配置的项目坐标
启动时自动配置
3. 监听机制
SpringBoot的监听机制,其实是对java提供的事件监听机制的封装
Java中的事件监听机制定义了以下几个角色:
- 事件: Event, 继承java.util.EventObject类的对象
- 事件源: Source , 任意对象Object
- 监听器: Listener 实现java.util.EventListener接口的对象
SpringBoot在项目启动时,会对几个监听器进行回调,我们可以实现这些监听器接口,在项目启动时完成一些操作
- ApplicationContextInitializer 项目图标加载后监听 ```java package com.itheima.springbootinit.listener;
import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.stereotype.Component;
@Component public class MyApplicationContextInitializer implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext applicationContext) { System.out.println(“ApplicationContextInitializer…initialize”); } }
<br />并且配置resource下的 META-INF 的spring.factories配置
org.springframework.context.ApplicationContextInitializer=com.itheima.springbootinit.listener.MyApplicationContextInitializer
-SpringApplicationRunListener 生命周期监听```javapackage com.itheima.springbootinit.listener;import org.springframework.boot.ConfigurableBootstrapContext;import org.springframework.boot.SpringApplication;import org.springframework.boot.SpringApplicationRunListener;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.core.env.ConfigurableEnvironment;import org.springframework.stereotype.Component;public class MySpringApplicationRunListener implements SpringApplicationRunListener {public MySpringApplicationRunListener(SpringApplication application, String[] args) {}@Overridepublic void starting(ConfigurableBootstrapContext bootstrapContext) {System.out.println("starting...项目启动中");}@Overridepublic void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {System.out.println("environmentPrepared...环境对象开始准备");}@Overridepublic void contextPrepared(ConfigurableApplicationContext context) {System.out.println("contextPrepared...上下文对象开始准备");}@Overridepublic void contextLoaded(ConfigurableApplicationContext context) {System.out.println("contextLoaded...上下文对象开始加载");}@Overridepublic void started(ConfigurableApplicationContext context) {System.out.println("started...上下文对象加载完成");}@Overridepublic void running(ConfigurableApplicationContext context) {System.out.println("running...项目启动完成,开始运行");}@Overridepublic void failed(ConfigurableApplicationContext context, Throwable exception) {System.out.println("failed...项目启动失败");}}
并且配置resource下的 META-INF 的spring.factories配置
org.springframework.boot.SpringApplicationRunListener=com.itheima.springbootinit.listener.MySpringApplicationRunListener
- CommandLineRunner ```java package com.itheima.springbootinit.listener;
import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component public class MyCommandLineRunner implements CommandLineRunner { @Override public void run(String… args) throws Exception { System.out.println(“CommandLineRunner…run”); System.out.println(Arrays.toString(args)); //java运行传递的参数 } }
-ApplicationRunner```javapackage com.itheima.springbootinit.listener;import org.springframework.boot.ApplicationArguments;import org.springframework.boot.ApplicationRunner;import org.springframework.stereotype.Component;import java.util.Arrays;@Componentpublic class MyApplicationRunner implements ApplicationRunner {@Overridepublic void run(ApplicationArguments args) throws Exception {System.out.println("ApplicationRunner...run");System.out.println(Arrays.toString(args.getSourceArgs())); //java运行传递的参数}}
3.1. 启动流程

4. 监控
SpringBoot自带监控功能Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况 Bean加载情况 配置属性 日志信息

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
访问localhost:8080/acruator
- 开启(health)健康检查完整信息
management.endpoint.health.show-details=always
- 将所有的监控endpoint暴露出来
management.endpoints.web.exposure.include=*
5. Spring Boot Admin
Spring Boot Admin是一个开源社区项目 用于管理和监控SpringBoot应用程序
分服务端和客户端 客户端用于查看监控 服务端用于监控Spring
服务端

<dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-server</artifactId><version>2.5.0</version></dependency>
在启动类中加上 注解 @EnableAdminServer 用于监控springboot
客户端
创建另外一个项目

<dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-client</artifactId><version>2.5.0</version></dependency>
在application配置admin.server地址
spring.boot.admin.client.url=http://localhost:8080 #对应的是server的ip和端口management.endpoint.health.show-details=alwaysmanagement.endpoints.web.exposure.include=*

6. 部署
SpringBoot项目开发完毕后,支持两种方式部署到服务器上
jar包(官方推荐)
直接在maven中打包即可war包
在pom文件中packageing定义为war包
启动类继承 SpringBootServletInitializer 类 重写configure方法@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {return builder.sources(SpringbootProfilesApplication.class); //将启动类字节码文件传递过去}
放置war包到tomcat的webapps的目录下启动tomcat即可
