《2022问》3:为什么 Spring Boot 能够自动加载并使用默认配置(或自定义配置)初始化 starter 组件?

        号称几乎零配置的 Spring Boot 早已成为了N多开发者的必备工具了,以至于题目的问题有点像在问“为什么我的刀能砍柴”,那我肯定会毫不客气地回答你“我的刀不仅可以砍柴还能砍盔甲”!它就是会自动配置的,项目启动的时候,项目自动读取相关配置文件去初始化就行了。

        我们来思考一个问题,我有一个基于 Spring Boot 的组件,张三引用了我这个组件,那么我这个组件是必然在张三的项目启动后自动初始化的吗?如果是,那么如果某个组件是不需要自动初始化的话,Spring Boot 是会对它自动初始化还是不会初始化呢?要知道,Spring Boot 通常是是使用 Java 配置类来初始化的,是不是每个组件只要有 @Configuration 注解的类都会被自动执行呢?而且,既然某个组件是在项目启动后自动初始化的,那么我们又是如何做到在yml之类的配置文件中更改某个组件的初始化参数值的呢?

        其实,Spring Boot 只会知道哪个项目需要自动加载,这是由它提供的一个加载流程决定的,需要自动加载的项目需要按照这个流程去实现,要让 Spring Boot 能够按照这个流程最终将这个项目给加载好。

        这个流程是这样的。

        首先,需要自动加载的项目都要在类路径下创建一个 META-INFO/spring.factories 文件,否则 Spring Boot 在启动时不会对这个项目做任何的操作。在 spring.factories 文件中,要有一个名为 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的参数,它指定了自动加载的 Java 配置类(可以有多个),从命名来看就能知道,这是一个 Spring Boot 在自动加载时所需要用到的参数。简单说就是,如果这里没有这个参数,Spring Boot 也是不知道你要如何初始化自己的项目的,而这个参数所指定的是该项目已经定义好的、有 @Configuration 注解的配置类,它必须包含包名,以下是 RockMQ 中的该配置,可以当作一个示例来看:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.alibaba.cloud.stream.binder.rocketmq.config.RocketMQComponent4BinderAutoConfiguration

        上面的配置表名,RockMQ 将通过 RocketMQComponent4BinderAutoConfiguration 来实现自动初始化,需要 Spring Boot 项目在启动的时候执行(赘述一下,如果需要执行多个配置类,那么就在这里配置多个,英文逗号隔开),否则 Spring Boot 不会做任何操作。

        在这些配置类中将会去读取它所需要的配置信息,配置信息的key值需要是全局唯一的;又或者,项目中创建了读取配置信息的类,通过某个唯一的前缀,将其下的所有配置信息读取到类中。

@ConfigurationProperties(prefix = "spring.cloud.stream.rocketmq.binder" )

public class RocketMQBinderConfigurationProperties

        上面的配置信息类就获取了 spring.cloud.stream.rocketmq.binder 前缀下的所有配置信息,这些配置信息是在我们自己创建的项目中自定义配上去的。如果我们的项目中没有给出相关的配置,那么它们通常会有默认值,这也是实现“约定大于配置”的过程,它减少了我们学习某个项目的每个配置项的时间,也降低了配置出错的概率,还统一了配置思路。

        而我们自己做的 Spring Boot 项目需要使用 @EnableAutoConfiguration 注解去启动自动加载配置,我们通常是使用 @SpringBootApplication 注解,它包含了前者。启动自动加载后,Spring Boot 会通过 @Import 加载 AutoConfigurationImportSelector 类,这个类再去读取所有包中的类路径下的 META-INFO/spring.factories 文件(这里就对应上了前述的每个项目都自己定义了的该文件),取出 org.springframework.boot.autoconfigure.EnableAutoConfiguration 对应的值并加载这些配置类。

        来到这里,Spring Boot 就能对相关的项目进行自动加载了,它并没有使用到什么特别的技术,实质上只是定义了一个加载流程,所有的项目都只要遵守并实现这个流程,就能使得这个项目在被其他项目引用时达到自动加载的效果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章