实现SpringBootStarter(一): SpringBoot Auto Configuration 流程

864 阅读2分钟

空洞的介绍流程,可能看了后还是不知所云,这里以SpringBoot 自动配置 rocketmq-spring-boot 的过程,介绍整个流程。先确定组件的版本

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot</artifactId>
    <version>2.0.2</version>
    <scope>compile</scope>
</dependency>

注意:SpringBoot auto configuration 想要生效,需要在启动类通过 @EnableAutoConfiguration 开启该功能

1. 流程分析

  1. SpringBoot 在启动的时候会扫描classpath下所有jar包内的 META-INF/spring.factories 文件。所以SpringBoot在启动时会扫描 rocketmq-spring-boot.jar 内 META-INF/spring.factories 文件, 文件具体内容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration
  1. 根据 spring.factories 内配置,SpringBoot 会去加载 RocketMQAutoConfiguration 类,该类的具体内容如下:
package org.apache.rocketmq.spring.autoconfigure;

@Configuration
@EnableConfigurationProperties(RocketMQProperties.class)
@ConditionalOnClass({ MQAdmin.class, ObjectMapper.class })
@ConditionalOnProperty(prefix = "rocketmq", value = "name-server")
@Import({ JacksonFallbackConfiguration.class, ListenerContainerConfiguration.class })
@AutoConfigureAfter(JacksonAutoConfiguration.class)
public class RocketMQAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(DefaultMQProducer.class)
    @ConditionalOnProperty(prefix = "rocketmq", value = {"name-server", "producer.group"})
    public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties) {
        // 具体逻辑
    }

    @Bean(destroyMethod = "destroy")
    @ConditionalOnBean(DefaultMQProducer.class)
    @ConditionalOnMissingBean(RocketMQTemplate.class)
    public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, ObjectMapper rocketMQMessageObjectMapper) {
        // 具体逻辑
    }

    @Bean
    @ConditionalOnBean(RocketMQTemplate.class)
    @ConditionalOnMissingBean(TransactionHandlerRegistry.class)
    public TransactionHandlerRegistry transactionHandlerRegistry(RocketMQTemplate template) {
        // 具体逻辑
    }

    @Bean(name = RocketMQConfigUtils.ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME)
    @ConditionalOnBean(TransactionHandlerRegistry.class)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public static RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor(
        // 具体逻辑
    }
}
  1. RocketMQAutoConfiguration 类自动配置关键点分析
  • Configuration:表明这是一个配置类
  • @EnableConfigurationProperties(RocketMQProperties.class): 自动加载RocketMQProperties.class 类,具体详情见第4节。
  • @Bean 修饰了类中的多个方法,或自动创建 Bean。包括:DefaultMQProducer,RocketMQTemplate,TransactionHandlerRegistry,RocketMQTransactionAnnotationProcessor。
  1. RocketMQProperties 类分析,该类去除了方法后的内容如下:
@SuppressWarnings("WeakerAccess")
@ConfigurationProperties(prefix = "rocketmq")
public class RocketMQProperties {
    private String nameServer;
    private Producer producer;
    
    public static class Producer {
        private String group;
        private int sendMessageTimeout = 3000;
        private int compressMessageBodyThreshold = 1024 * 4;
        private int retryTimesWhenSendFailed = 2;
        private int retryTimesWhenSendAsyncFailed = 2;
        private boolean retryNextServer = false;
        private int maxMessageSize = 1024 * 1024 * 4;
        private String accessKey;
        private String secretKey;
        private boolean enableMsgTrace = true;
        private String customizedTraceTopic = MixAll.RMQ_SYS_TRACE_TOPIC; 
    }
}

通过上面的代码可知 RocketMQProperties 其实就是 RocketMQ 的配置文件,通过该文件也可以得知 RocketMQ 所有支持的配置项和默认值。 第三节中 @EnableConfigurationProperties(RocketMQProperties.class) 的作用就是让 SpringBoot 自动生成该 RocketMQProperties 类的对象,并读取配置文件的内容给类对象的属性复制。 从 RocketMQProperties 内容可以推断出,配置文件的格式为:

rocketmq:
    nameServer: nameServer
    producer:
        group:
        sendMessageTimeout:3000
        compressMessageBodyThreshold:1024 * 4
        retryTimesWhenSendFailed:2
        retryTimesWhenSendAsyncFailed:2
        retryNextServer:false
        maxMessageSize:1024 * 1024 * 4
        accessKey: accessKey
        secretKey: secretKey
        enableMsgTrace:true
        customizedTraceTopic:RMQ_SYS_TRACE_TOPIC
  1. 通过上面的分析,我们可以大致的知道SpringBoot 自动配置的大致流程,以 rocketmq-spring-boot 为例,我们在使用时不需要自己再去创建 Bean,SpringBoot已经帮我们自动生成并配置好了。
@Resource
RocketMQProperties rocketMQProperties;
@Resource
DefaultMQProducer defaultMQProducer;
@Resource
RocketMQTemplate rocketMQTemplate;
@Resource
TransactionHandlerRegistry transactionHandlerRegistry;
@Resource
RocketMQTransactionAnnotationProcessor rocketMQTransactionAnnotationProcessor;

2. 总结

通过上面的分析,可以了解 SpringBoot 自动配置的整个流程,如果我们需要实现该功能需要完成如下步骤:

  1. 定义 Properties 配置类(
  2. 定义 AutoConfiguration 类
    • @Configuration 注解修饰
    • @EnableConfigurationProperties(Properties.class) 加载第一步定义的配置文件
    • @Bean 定义需要 Spring 管理的 Bean 对象
  3. META-INF/spring.factories 配置自动加载信息
# 第二步定义的 AutoConfiguration 类的完整包路径
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.***.AutoConfiguration