您的当前位置:首页正文

Spring Boot AutoConfiguration 解密

来源:华佗小知识

Boot 中提供了 @EnableAutoConfiguration 这个注解来实现spring的context以及配置一些它“揣测”我们可能需要的配置。那么我们下面来分析下它揣测的过程。

@Configuration
public class DBConfig {
    @Bean
    @Conditional(MongoDriverCondition.class)
    public DbConfig getMongoClient() {
        return new MongoClient();
    }
    
    @Bean
    @Conditional(PostgresDriverCondition.class)
    public DbConfig getPGClient() {
        return new PGClient();
    }

}

public class MongoDriverCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext,
        AnnotatedTypeMetadata metadata) 
    try {
            Class.forName("com.mongodb.Server");
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
}

Boot 的 @EnableAutoConfiguration 的关键点就是使用了 @Conditional. 首先当我们使用注解 @EnableAutoConfiguration 在我们的应用的主入口类上,在项目启动时 Boot 便会加载 spring-boot-autoconfiguration 包里面的 spring.factories ,截取部分内容如下:

    # Auto Configure
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
    org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
    org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
    org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\
    org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,\
    org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
    org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\

意思就是要加载这些配置文件,置于怎么判断要不要加载,我们拿 AMQP 举个栗子。 比方说我们想要使用 RabbitMQ 来作为我们项目的MQ,(假定我们使用gradle)那么我们只需要引入 compile("org.springframework.boot:spring-boot-starter-amqp") 这个依赖就OK了,然后就可以顺水推舟写我们的各种receiver和publisher了,那么为什么这个加了这个依赖就好了呢? 我们可以看下它的源码,发现只有一个pom文件, 里面有如下依赖:

  • spring-messaging
  • spring-rabbit

此时我们再去看 class RabbitAutoConfiguration, 注意 它有个 @Configuration注解,表明它是一个普通的 spring 的 Config 类,接着有如下两个注解:

  • @ConditionalOnClass({ RabbitTemplate.class, Channel.class })
  • @EnableConfigurationProperties(RabbitProperties.class)

第一个注解 @ConditionalOnClass 的意思就是说当后面 ()里面指定的类存在于 ClassPath 里面时,condition的条件成立,就加载目标类。 对于此处,指定的两个 Class已经被包含在 spring-messagingspring-messaging 这两个依赖里面,所以 RabbitAutoConfiguration 会在项目启动时被加载,故而我们可以直接使用rabbit了。顺便说下第二个注解,它的意思是说把配置文件里面的 形如 spring.rabbitmq.XXX(这个前缀定义在 RabbitProperties里面)的值绑定到 Class RabbitProperties 上面。 AMQP的分析就到这里,其他的自动配置类也是相似的原理,比如想要使用 Ehcache,只要在依赖中加上 Ehcache , 那么项目中的 CacheManager 的实现类就是 Ehcache 对应的了。

The end.