Springboot自动配置原理
Springboot只需要导入starter,就可以愉快地写代码了,其余的配置都不需要我们来考虑,显得十分便捷,那么Springboot这种自动配置机制的原理是怎样的呢?
Springboot开发流程
以web应用程序开发为例:
导入starter-web
,即导入了web开发场景
编写主程序,并且主程序类被注解@SpringBootApplication
标识
编写业务代码,全程无需关心各种业务整合(Springboot代替我们完成了)
导入 starter-web
导入web开发的场景启动器starter-web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
这个场景启动器对应的文件为spring-boot-starter-web-3.1.5.pom
,它导入了相关场景的所有依赖。例如spring-boot-starter-json
,spring-boot-starter-tomcat
,springmvc
等。
值得注意的是,每个场景启动器都引入了一个核心场景启动器,即spring-boot-starter
。
核心场景启动器 spring-boot-starter
核心场景启动器对应的文件为spring-boot-starter-3.1.5.pom
,可以看到核心场景启动器也引入了若干依赖,其中比较重要的一个是自动配置包,即spring-boot-autoconfigure
。
spring-boot-autoconfigure
包下包含了springboot
官方所有场景的配置类,只要这个包下的类可以生效,那么Springboot
官方写好的整合功能就生效了。
但是,问题在于,Springboot
默认只扫描主程序所在的包及其下面的子包,并不能扫描到spring-boot-autoconfigure
包下的配置类,Springboot是如何让它们生效的呢?
主程序
一个简单的主程序示例如下:
// springboot必需的注解
// 表示这是一个springboot应用
@SpringBootApplication
public class MainApp {
public static void main(String[] args) {
SpringApplication.run(MainApp.class,args);
}
}
主程序上带有注解@SpringBootApplication
,这个注解由三个注解组成,分别是@SpringBootConfiguration
(标识这是一个配置类),@EnableAutoConfiguration
和@ComponentScan
。
@EnableAutoConfiguration 注解
@EnableAutoConfiguration
很关键,它是Springboot开启自动配置的核心注解。
@EnableAutoConfiguration
上有一个@Import({AutoConfigurationImportSelector.class})
,其作用是给容器中导入组件,这里是起到批量导入的功能,允许类AutoConfigurationImportSelector
指定需要导入哪些组件。
这里使得Springboot
启动会默认加载100多个配置类,这些类来自于spring-boot-autoconfigure
包下META-INF\spring\org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件指定的所有类,名称均为xxxAutoConfiguration形式。
虽然Springboot
默认只扫描主程序所在的包及其子包,但是却通过注解把自动配置类都导入了进来。
虽然这些类全部都被导入了,但是这些类不一定都生效。
自动配置类生效
以Kafka
的自动配置类为例:
@AutoConfiguration
@ConditionalOnClass({KafkaTemplate.class})
@EnableConfigurationProperties({KafkaProperties.class})
@Import({KafkaAnnotationDrivenConfiguration.class, KafkaStreamsAnnotationDrivenConfiguration.class})
public class KafkaAutoConfiguration {
private final KafkaProperties properties;
KafkaAutoConfiguration(KafkaProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean({KafkaConnectionDetails.class})
PropertiesKafkaConnectionDetails kafkaConnectionDetails(KafkaProperties properties) {
return new PropertiesKafkaConnectionDetails(properties);
}
······
注意到,这个自动配置类之上,有一个注解@ConditionalOnClass({KafkaTemplate.class})
,这意味着只有当类路径下存在KafkaTemplate
这个类,也就是说我导入了这个包,整个配置才会生效。
这就是按需生效,不是导入的类都能生效,而是通过条件注解来控制哪些类生效。
在自动配置类中,会使用@Bean
注解给容器中放一堆组件,这样Springboot
就完成了自动配置。
通过配置文件配置
在写好了一个web程序后,为什么通过配置文件(.properties
)就可以配置应用程序的信息,例如端口号等?
这是因为每个自动配置类之上都有一个注解形似:
@EnableConfigurationProperties({KafkaProperties.class})
,它用于把配置文件中指定前缀的属性值封装到xxxProperties
属性类中。
在自动配置类生效时,会自动加载配置文件中的属性,这样只需要程序重启即可更新配置。
文章来源:
Author:月梦
link:https://ymiir.netlify.app//springboot/Springboot自动配置原理.html