简单详细的SpringBoot自动配置原理解析
前言
上一篇文章我们介绍了SpringFactoriesLoader
,之所以介绍SpringFactoriesLoader
是因为我们这篇文章要介绍的SpringBoot的自动配置会用到SpringFactoriesLoader
的知识。闲话少叙,让我们直入主题。
环境
spring-boot 1.5.8.RELEASE
从启动类开始
@SpringBootApplication
public class HelloworldDemoApplication { public static void main(String[] args) { SpringApplication.run(HelloworldDemoApplication.class, args); }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
如上,就是我们SpringBoot应用的启动类。让我们把眼光聚焦到@SpringBootApplication
注解上面。这个注解是SpringBoot项目的主配置类。
@SpringBootApplication
//省略部分注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
根据前几篇的介绍,我们可以知道@SpringBootApplication
注解是一个组合注解。
@SpringBootConfiguration
注解 表示这是SpringBoot的配置类,
@ComponentScan
开启组件扫描
@EnableAutoConfiguration
这个注解的作用就是让SpringBoot开启自动配置。自动配置的奥秘全都在这里:
@EnableAutoConfiguration
//省略部分注解
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
- 1
- 2
- 3
- 4
- 5
- 6
如上我们可以看到EnableAutoConfiguration
注解上有两个注解
@AutoConfigurationPackage
注解,
从字面意思上来看就是自动配置包。点进去可以看到就是⼀个@Import
注解:@Import(AutoConfigurationPackages.Registrar.class)
,导⼊了⼀个
Registrar 的组件,这个注解的作用就是将主配置类(@SpringBootConfiguration
标注的类)所在的包及其下面所有子包里面所有的组件扫描到IOC容器中。所以说,默认情况下主配置类所在包及其子包以外的组件,Spring IOC容器是扫描不到的。@Import(AutoConfigurationImportSelector.class)
通过@Import
导入了AutoConfigurationImportSelector
类,而这个类的selectImports
方法会通过SpringFactoriesLoader
得到大量的配置类。而每个配置类则根据条件化配置类做出决策,以实现自动配置的功能。下面就让我们来看看selectImports
方法。
AutoConfigurationImportSelector的selectImports方法
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//省略部分代码
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
return StringUtils.toStringArray(configurations);
} protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
return configurations;
} protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
如上代码,自动配置核心的代码我都罗列出来了,最核心的就是loadFactoryNames
方法,其主要有三步:
- 从classpath下获取所有
META-INF/spring.factories
这个文件下的信息。 - 将上面获取到的信息封装成Enumeration返回
- 遍历Enumeration,然后获取key为
EnableAutoConfiguration
下的所有值。
META-INF/spring.factories
这类⽂件是什么就不懵了。当然在很多第三⽅依赖中
都会有这个⽂件,⼀般每导⼊⼀个第三⽅的依赖,除了本⾝的jar包以外,还会有⼀个 xxx-spring-boot-autoConfigure,这个就
是第三⽅依赖⾃⼰编写的⾃动配置类。我们现在就以 spring-boot-autocongigure 这个依赖来说下,其下面的META-INF/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.jdbc.DataSourceAutoConfiguration,\
- 1
- 2
- 3
- 4
- 5
配置类注册到IOC容器的流程图
然后就是实例化这些配置类注册到IOC容器中。流程如下:
以DataSourceAutoConfiguration进行说明
通过上面的方式,所有的自动配置类都被导进主配置类中,但是这么多的配置类,明显有很多我们平常是没有使用到的,没必要全部生效,下面我们以DataSourceAutoConfiguration
配置类为例来看一下自动配置类是如何工作的:
@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration {
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
@Configuration
注解表明了DataSourceAutoConfiguration
类是一个JavaConfig配置类。@ConditionalOnClass
只有当classpath中存在DataSource
类或者EmbeddedDatabaseType
类时才启动这个配置。@EnableConfigurationProperties
这个注解的作用是将将DataSource
类注入到IOC容器中。@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
是要导入额外的配置DataSourcePoolMetadataProvidersConfiguration
。
DataSourceProperties 类
下面我们就来一个个看一下:首先是DataSourceProperties
类:
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties
implements BeanClassLoaderAware, EnvironmentAware, InitializingBean {
private ClassLoader classLoader;
private Environment environment;
private String name = "testdb"; private boolean generateUniqueName; private Class<? extends DataSource> type; private String driverClassName;
private String url; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
DataSourceProperties 通过@ConfigurationProperties
注解将配置文件的前缀为(spring.datasource)的配置信息与自身的属性绑定。所有在配置⽂件中能配置的属性都是在 xxxProperties 类中封装着;配置⽂件能配置什么就可以参照某个功能对应的这个属性
类。
DataSourcePoolMetadataProvidersConfiguration 类
@Configuration
public class DataSourcePoolMetadataProvidersConfiguration {
@Configuration
@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
static class TomcatDataSourcePoolMetadataProviderConfiguration {
} @Configuration
@ConditionalOnClass(HikariDataSource.class)
static class HikariPoolDataSourceMetadataProviderConfiguration {
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
DataSourcePoolMetadataProvidersConfiguration
类是数据库连接池提供者的一个配置类。即classpath中存在org.apache.tomcat.jdbc.pool.DataSource.class
则使⽤tomcat-jdbc连接池,如果classpath中存在 HikariDataSource.class则使⽤ Hikari连接池,如果存在org.apache.commons.dbcp.BasicDataSource.class
则启用dbcp 连接池。
总结
- SpringBoot启动时会扫描项目所依赖的JAR包,寻找包含spring.factories文件的JAR包。
- 根据spring.factories配置加载EnableAutoConfiguration
其中给容器中自动配置添加组件的时候,会从propeties
类中获取配置文件中指定这些属性的值。xxxAutoConfiguration:⾃动配置类给容器中添加组件。xxxProperties:封装配置⽂件中相关属性。 - 根据@Conditional注解的条件,进行自动配置并将Bean注入Spring容器
文章来源: feige.blog.csdn.net,作者:码农飞哥,版权归原作者所有,如需转载,请联系作者。
原文链接:feige.blog.csdn.net/article/details/105961992
- 点赞
- 收藏
- 关注作者
评论(0)