条件注解的理解:该注解指定了一些条件,只有符合这些条件,被该注解修饰的类或方法才能生效。
这些条件可以是yml配置文件里面的属性等数据是否存在,也可以是一些依赖驱动是否存在的条件、也可以是指定的bean是否存在等。
springboot的自动配置
★ 自动配置
Spring Boot的自动配置通常可根据依赖库自动触发
——当Spring Boot检测到项目中包含某些框架的JAR包时,Spring Boot就会触发自动配置。
其实通过@EnableAutoConfiguration注解来启动
▲ 其实你用到@SpringBootApplication,该注解其实就组合了@EnableAutoConfiguration注解。
因此应用主类只要使用@SpringBootApplication注解,就相当于添加@EnableAutoConfiguration注解。
★ 自动配置的替换原则
Spring Boot会为我们自动配置很多Bean——这些Bean就是整合某个框架所需要的基础Bean。
举例来说,以整合MyBatis为例,典型至少需要DataSource、SqlSessionFactory、SqlSessionTemplate……
如果不用Spring Boot,开发者就需要自行在容器中配置这些基础Bean来完成整合。
用了Spring Boot之后,这些完成整合的基础Bean就交给Spring Boot来自动配置了。
▲ 两种常见的替换原则:
A. 一旦你在容器中配置了某种类型的(DataSource)的Bean,Spring Boot将不再自动配置该类型的Bean。
这意味着开发者定制配置替换了Spring Boot的自动配置。
—这种是基于类型的替换原则。
基于注解: @ConditionalOnMissingBean({DataSource.class})
B. 一旦你在容器中配置了某个特定Id的(sqlSessionTemplate)的Bean,Spring Boot将不再自动配置该ID的Bean。
这意味着开发者定制配置替换了Spring Boot的自动配置。
——这种是基于ID的替换原则。
基于注解:@ConditionalOnMissingBean(name = "sqlSessionTemplate")
▲ 当开发者要替换Spring Boot的自动配置时,通常只要做一件事情
——在Spring容器中添加自定义的配置,一旦你添加了自定义配置,Spring Boot自动配置就自动“退场”了。
★ 禁用自动配置
只要你使用了@EnableAutoConfigation注解,Spring Boot会自动启用所有XxxAutoConfiguration自动配置类。
而XxxAutoConfiguration就是一个配置类(通常它带有@Configuration注解修饰),默认Spring Boot会扫描并加载它们
【备注】:Spring Boot官方的自动配置类通常都位于spring-boot-autoconfigure.jar包中。
▲ 禁用某个自动配置类:
通过@EnableAutoConfiguration注解的如下属性来指定:
- exclude:该属性值可以是一个Class数组,用于禁用一个或多个自动配置类。
- excludeName:与前一个属性的作用基本相同,只不过此处指定一个或者多个自动配置类的完整类名的字符串形式。(就是全限定类名的形式)
例子:
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
——禁用DataSourceAutoConfiguration.class自动配置类。
在application.properties文件中通过spring.autoconfigure.exclude
例子:
spring.autoconfigure.exclude=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
▲ 自动配置和定制配置
自动配置确实非常简单,所以Spring Boot上手很简单
但Spring Boot自动配置只能处理那些最通用的情况,实际项目往往都需要定制配置,
因此你必须掌握Spring Boot定制配置的原理,并能用定制配置去替换自动配置。
★ 自动配置的本质
就是由自动配置类提前配置了整合某个框架所需的基础Bean。
——如果你不用Spring Boot,那么整合框架所需的这些基础Bean应该由开发者来配置。
用了Spring Boot之后,这些Bean就交给Spring Boot的自动配置类来配置,开发者就无需手动配置,比较简单。
=========================================================
springboot最核心的就是条件注解,真正属于springboot的注解。
而之前的那些 @Controller、@RestController、@PathVariable @Bean 这些其实不属于springboot本身,其实是属于spring mvc,都是属于spring的框架本身
条件注解分类:
类条件注解:
@ConditionalOnClass、
@ConditionalOnMissingClass
Bean条件注解:
@ConditionalOnMissingBean、
@ConditionalOnSingleCandidate
@ConditionalOnBean
@ConditionalOnMissingFilterBean
属性条件注解:@ConditionalOnProperty
资源条件注解:@ConditionalOnResource
Web应用条件注解:
@ConditionalOnWebApplication.
@ConditionalOnNotWebApplication.
@ConditionalOnWarDeployment
SpEL表达式条件注解:
@ConditionalOnExpression
特殊条件注解:
@ConditionalOnCloudPlatform、
@ConditionalOnJava、
@ConditionalOnJndi.
@ConditionalOnRepositorylype
★ 类条件注解
类条件有两个@ConditionalOnClass、@ConditionalOnMissingClass,
分别表示某些类存在或不存在时被修饰的配置类或被修饰的配置方法生效。
@ConditionalOnClass:表示某些类【存在】时被修饰的配置类或被修饰的配置方法生效。
@ConditionalOnMissingClass表示某些类【不存在】时被修饰的配置类或被修饰的配置方法生效。
@ConditionalOnClass注解可通过value或name属性指定它所要求存在的类。
@ConditionalOnMissingClass则只能通过value属性指定它所要求不存在的类。
代码演示 类条件注解 中的 @ConditionalOnClass
@ConditionalOnClass:表示某些类【存在】时被修饰的配置类或被修饰的配置方法生效。
演示使用注解 @ConditionalOnClass ,表示这个被这个注解修饰的类,得注解限制的一些东西存在,该类才能生效。
比如这个被 @ConditionalOnClass 注解修饰的类,
通过@ConditionalOnClass(name = “com.mysql.cj.jdbc.Driver”) 修饰,就是要求当前项目中存在 MYSQL 驱动时,这个配置类才会生效。
得有这个mysql的驱动,在启动类中获取这个配置类bean才能生效。
如图,有了@ConditionalOnClass(name = “com.mysql.cj.jdbc.Driver”)声明的mysql驱动,就可以在成功获取这个MyConfig01配置类这个bean(这个配置类在启动的时候会被加载成bean)
MyConfig01类贴了@ConditionalOnClass(name = “com.mysql.cj.jdbc.Driver”),如果没有mysql驱动,那么如图
★ Bean条件注解
@ConditionalOnBean:特定Bean存在时条件生效。
@ConditionalOnMissingBean:特定Bean不存在时条件生效。
@ConditionalOnSingleCandidate:特定Bean存在且唯一时条件生效。
@ConditionalOnMissingFilterBean:专门用于检查Filter。
- 如果指定了name属性,表明根据Bean ID进行检查;否则根据Bean类型进行检查。
【注意】:使用Bean条件注解时,务必要注意Bean的加载顺序。
换而言之,你要检查某个Bean是否存在时,一定要保证你的该条件注解的执行时机在你检查的bean之后。
示例:
@ConditionalOnBean(name = "abc") ——当容器中有ID为abc的Bean时,下面的配置才生效。
可能出现的情况时,虽然容器中已经配置了ID为abc的Bean,但由于abc 这个 Bean的加载时机较晚,晚于@ConditionalOnBean这个条件注解的加载时机,因此同样可能导致该条件失效。
▲ 控制顺序的注解:
@AutoConfigureBefore:只能修饰自动配置类,要求被修饰的配置类必须在指定配置类之前生效。
@AutoConfigureAfter:只能修饰自动配置类,要求被修饰的配置类必须在指定配置类之后生效。
@AutoConfigureOrder:可修饰配置类、方法、成员变量,指定一个自动配置顺序编号。编号越小的越先加载
这3个注解主要用于控制自动配置类之间的顺序,对类内部的配置方法的顺序一般不做控制。
@AutoConfigureOrder 官方说是能控制配置类、方法、成员变量的加载顺序,但其实只能控制类层面的加载顺序,如果要控制一个类中的多个方法的加载顺序,是没有效果的。
代码演示 Bean条件注解 @ConditionalOnBean
@ConditionalOnBean:特定Bean存在时条件生效。
创建一个userService 接口,然后把这个接口用@Bean 注解修饰为容器中的bean。
然后用@ConditionalOnBean(name = “getDataFormat”)修饰bean方法。
可以看出因为有 getDataFormat 这个bean,所以 userService 这个bean方法才能生效。
如果把两个bean的顺序反过来,就会因为加载时机的问题,导致出问题。
如图:我们把userService方法写在getDataFormat方法前面,那么项目在启动加载的时候,就会先加载userService方法,但是userService方法要生效的前提是有getDataFormat这个bean,但是此时的getDataFormat 方法加载时机比较慢,虽然代码写了,但是因为还没加载,在@ConditionalOnBean(name = “getDataFormat”) 看来就是没有getDataFormat这个bean,所以userService方法不生效,所以在启动类那边,ctx.getBean(“userService”),就找不到userService这个bean。
演示控制顺序的注解 @AutoConfigureOrder
@AutoConfigureOrder:可修饰配置类、方法、成员变量,指定一个自动配置顺序编号。编号越小的越先加载
这3个注解主要用于控制自动配置类之间的顺序,对类内部的配置方法的顺序一般不做控制。
@AutoConfigureOrder 官方说是能控制配置类、方法、成员变量的加载顺序,但其实只能控制类层面的加载顺序,如果要控制一个类中的多个方法的加载顺序,是没有效果的。
如图:即使加了注解,但是这个注解修饰方法,并没有效果,说是只有修饰类有效果
如图:还是得让getDataFormat方法先执行靠谱。