这是我参与8月更文挑战的第13天,活动详情查看:8月更文挑战
- SpringBoot学习(一):SpringBoot初始化
- SpringBoot学习(二):SpringBoot项目结构
- SpringBoot学习(三):SpringBoot与Spring MVC
- SpringBoot学习(四):SpringBoot的配置体系
通过之前的学习,了解了SpringBoot项目配置体系,这次就来学习一下SpringBoot是如何实现自动配置的。
SpringBoot自动配置原理
@SpringBootApplication注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class}),
@Filter(type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class})
})
public @interface SpringBootApplication {
...
}
- @SpringBootApplication注解作为一个组合注解,本身由
@SpringBootConfiguration
、@EnableAutoConfiguration
和@ComponentScan
三个注解组合而成。 - 在启动类中使用该三个注解代替@SpringBootApplication注解同样可以启动服务。
@ComponentScan注解
- @ComponentScan是Spring中的注解,用来扫描基于指定包路径下的所有需要注入的类(@Component、@Repository等注解所标注的类),并把相关的Bean定义批量加载到Ioc容器中。
- 可以通过
basePackages
属性来指定@ComponentScan扫描的范围,不指定时默认为@ComponentScan注解类所在包范围(即SpringBoot启动类包路径)。
@SpringBootConfiguration注解
- @SpringBootConfiguration注解没有新增内容,只是使用了Spring中的@Configuration注解,而@Configuration注解中提供了JavaConfig配置类实现。
- 使用@Configuration注解的类表示本身作为一个Ioc容器的配置类,Spring中有XML和JavaConfig两种配置方式,SpringBoot社区推荐使用JavaConfig的配置方式。
- XML配置方式需要在xml文件中使用标签注册和使用bean对象的关系。
- JavaConfig配置方式中使用@Configuration和@Bean注解来实现Spring配置类。其中@Configuration注解标识当前类作为Spring Ioc容器中bean的来源;@Bean注解方法则返回一个对象,并将该对象注册为Spring上下文中的bean。
@EnableAutoConfiguratuon注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
...
}
- @EnableAutoConfiguration注解与自动配置相关,借助@Import的帮助,将所有符合自动配置条件的bean定义加载到Ioc容器中。并根据类路径中的jar依赖为项目进行自动配置,如添加
spring-boot-starter-web
依赖,则SpringBoot会对Tomcat和Spring MVC进行自动配置。 - @EnableAutoConfiguration注解同样是一个复合注解,包含
@AutoConfigurationPackage
和@Import(AutoConfigurationImportSelector.class)
两个注解。
@Import(AutoConfigurationImportSelector.class)
- @Import(AutoConfigurationImportSelector.class)注解,借助EnableAutoConfigurationImportSelector将所有符合条件的@Configuration配置都加载到当前SpringBoot应用的Ioc容器中。
- 借助于Spring框架中的SpringFactoriesLoader工具类,@EnableAutoConfiguration注解可以从指定的配置文件META-INF/spring.factories中加载配置。SpringFactoriesLoader会将@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为Key,获取对应@Configuration类。
SpringBoot自动配置流程
- @EnableAutoConfiguration即开启自动配置注解,其通过SpringBootApplication注解标注到SpringBoot的启动类中,当启动类SpringBootApplication.run()执行时,@EnableAutoConfiguration注解便会生效。
- @EnableAutoConfiguration作为复合注解,其中包含了@Import(AutoConfigurationImportSelector.class)注解,引入了AutoConfigurationImportSelector类并执行其selectImports()方法。
- selectImports()方法内部使用了SpringFactoriesLoader.loadFactoryNames()方法来从classpath中扫描所有具有META-INF/spring.factories配置的Jar包。
- Jar包中的META-INF/spring.factories文件的内容以Key-Value形式存放,SpringFactoriesLoader类会以EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为Key,获取对应Value即一组以逗号分隔的XxxxAutoConfiguration类的全限定名。
- 针对获取到的所有XxxxAutoConfiguration类,其上标注有注解@EnableConfigurationProperties,并指定对应的XxxxProperties配置实体类,配置实体类上则使用@ConfigurationProperties注解来指向全局配置的属性值。
- 最终通过反射的方式实例化为对应的标注@Configuration的JavaConfig形式的Ioc容器配置类,最后汇总在一起加载到Ioc容器中。
- 至此,所有的全局配置属性对应的JavaConfig配置类会被自动封装成为bean并注入到Spring的Ioc容器中。