1. 理解自动装配bean
1.1 常用注解
@AutoConfiguration
(每个配置类都要加上)Class<?>[] after() default {};
Class<?>[] before() default {};
- 以上两个配置可以控制加载顺序;
- 不需要再增加
@Configuration
注解;
@AutoConfigureBefore
and@AutoConfigureAfter
@Configuration
@Conditional
(后面会详细讲到)@ConditianalOnClass
@ConditionalOnMissingClass
@ConditionalOnWebApplication
:只在web应用中加载;
@EnableConfigurationProperties
:配置文件参数内容,参照类RedisProperties
;@ConfigurationProperties(prefix = "spring.redis")
,该注解展示了配置文件前缀;
@DependsOn
:列举一些前置的注入bean,以备用,用在类上需要有@Component
自动扫描的时候才能生效;- 实际上控制了bean加载的顺序,优先加载指定的bean,然后加载当前bean;
- 销毁的时候,注解的bean优先与于依赖的bean销毁;
2. 定位自动装配的候选类
springboot
框架会自动扫描 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
进行引入,所以需要自动注入的***Configuration
文件都写在这个文件中。每个class
一行。
这里本质上是一个自动版的@Import。
示例:
# comments
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
如果需要引入特定的
Component
,使用@Import注解。
3. 条件注解
在所有自动装配类出现的地方,我们都因该时加上@Conditional
注解,允许使用的开发人员覆盖自动装配的bean,当然他们也可以选择什么也不做,使用默认的配置。
Spring Boot 提供了一些条件注解,可以注解在@Configuration
类或者@Bean
方法上。
3.1 有关类的判断
对于@Configuration
类来说,@ConditionalOnClass
和@ConditionalOnMissingClass
代表了在指定类存在或者不存在的时候进行加载。因为实际上注解的元数据使用ASM技术进行解析,所以可以使用value
参数来指定特定的类的class对象(可以是多个),或者使用name
参数来指定特定的类名(可以是多个),两种方式所指向的类即使不存在也不影响正常执行。
当@Bean
方法返回值是条件注解的的目标之时,可能会因为JVM加载顺序的问题导致加载失败,上文提到的两个注解可以用在@Bean
方法上。
3.2 有关bean的判断
@ConditionalOnBean
和@ConditionalOnMissingBean
,代表在指定bean存在或者不存在时加载。value
参数可以指定bean的class(多个),name
可以指定bean的名称(多个)。search
参数允许你限制ApplicationContext
即应用上下文的搜索范围,可选当前上下文,继承上层,或者是全部(默认)。
在@Bean
方法上使用时,默认参数为当前方法返回类型。
在使用@Bean注解时,建议使用具体类型而不是父类型进行指代。
3.3 配置条件
@ConditionalOnProperty
,指定配置项文件(例如dev,pro),prefix
属性规定了配置前缀,name
属性指定了应该被检查的参数。默认,所有存在且不等于false
的参数都会被匹配到,你也可以使用havingValue
和matchIfMissing
属性闯将更多的校验。
例子:@ConditionalOnProperty(name = "spring.redis.client-type", havingValue = "lettuce", matchIfMissing = true)
;
属性名 | 类型 | 解析 |
---|---|---|
name | String[] name() default {}; | 配置项全称,如果有prefix,可以省略prefix中的前缀部分 |
prefix | String prefix() default ""; | 统一的配置项前缀 |
havingValue | String havingValue() default ""; | 配置项需要匹配的内容,如果没有指定,那么配置的值等于false 时结果为false,否则结果都为true |
matchIfMissing | boolean matchIfMissing() default false; | 配置项不存在时的配置,默认为false |
3.4 源文件条件
@ConditionalOnResource
,指定源文件存在时引入。
例如:@ConditionalOnResource(resources = {"classpath:test.log"})
;
3.5 web 应用条件
@ConditionalOnWebApplication
和 @ConditionalOnNotWebApplication
,web应用或者不是web应用时启用,以下部分只要满足一个条件即为web 应用。
servlet-based
web 应用特点:
- 使用 Spring
WebApplicationContext
; - 定义了一个
session
作用域的bean; - 有一个
WebApplicationContext
;
reactive
web 应用特点:
-
使用了
ReactiveWebApplicationContext
; -
有一个
ConfigurableReactiveWebEnvironment
;
ConditionalOnWarDeployment
,仅限于使用war进行部署的场景,在嵌入式tomcat的场景里不会启用;
3.6 Spel表单式条件
ConditionalOnWarDeployment
,使用Spel表达式返回结果进行判断。
注意:在表达式中引用一个bean会导致这个bean非常早的被加载,此时还没有进行预加载(例如配置项的绑定),可能会导致不完成的加载。
参考
[2] 创建自己的配置文件