此前我们讲到,@EnableAutoConfiguration可以借助SpringFactoriesLoader这个特性将标注了@Configuration的JavaConfig类“一股脑儿”的汇总并加载到最终的ApplicationContext,不过,这其实只是“简化版”的说明,实际上,基于@EnableAutoConfiguration的自动配置功能有更加强大的调控能力,通过配合比如基于条件的配置能力或者调整加载顺序,我们可以对自动配置进行更加细粒度的调整和控制。
基于条件的自动配置
基于条件的自动配置来源于Spring框架中“基于条件的配置”这一特性。在Spring框架中,我们可以使用@Conditional这个Annotation配合@Configuration或者@Bean等Annotation来干预一个配置或者bean定义是否能够生效,其最终实现的效果或者语义类似于如下伪代码:
if( 符合@ Conditional 规定 的 条件){
加载 当前 配置( enable current Configuration) 或者 注册 当前 bean 定义;
}
要实现基于条件的配置,我们只要通过@Conditional指定自己的Condition实现类就可以了(可以应用与类型Type的标注或者方法Method的标注):
@Conditional({ MyCondition1. class, MyCondition2. class, ...})
最主要的是,@Conditional可以作为一个Meta Annotation用来标注其它的Annotation实现类,从而构建各色的复合Annotation,比如SpringBoot的autoconfigure模块就基于这一优良的革命传统,实现了一批这样的Annotation(位于org.springframework.boot.autoconfigure.condition包下):
- @ConditionalOnClass
- @ConditionalOnBean
- @ConditionalOnMissingClass
- @ConditionalOnMissingBean
- @ConditionalOnProperty
- ……
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({OnClassCondition.class})
public @interface ConditionalOnClass {
Class<?>[] value() default {};
String[] name() default {};
}
有了这些复合Annotation的配合,我们就可结合@EnbaleAutoConfiguration实现基于条件的自动配置了。
SpringBoot能够风靡,很大一部分功劳需要归功于它预先提供的一系列自动配置的依赖模块,而这些依赖模块都是基于以上@Conditional复合Annotation实现的,这也意味着所以的这些依赖模块都是按需加载的,还有复合某些特定条件,这些依赖模块才会生效,这也就是我们所谓的“智能”自动配置。
调整自动配置的顺序
在实现自动配置的过程中,除了可以提供基于条件的配置,我们还可以对当前要提供的配置或者组件的加载顺序进行相应的调整,从而让这些配置或者组件之间的依赖分析和组装可以顺利完成。
我们可以使用@org.springframework.boot.autoconfigure.AutoConfigureBefore或者@org.springframework.boot.autoconfigure.AutoConfigureAfter让当前配置或组件在某个其他组件之前或者之后进行,比如,假设我们希望某些JMX操作相关的bean定义在MBeanServer配置完成之后进行,那么我们就可以提供一个类似如下的配置:
@Configuration
@AutoConfigureAfter( JmxAutoConfiguration. class)
public class AfterMBeanServerReadyConfiguration {
@Autowired MBeanServer mBeanServer;
// 通过@ Bean 添加 必要 的 bean 定义
}