spring boot 自动配置原理
Posted 随风去。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring boot 自动配置原理相关的知识,希望对你有一定的参考价值。
1).spring boot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration
2).通过@EnableAutoConfiguration中AutoConfigurationImportSelector给容器中导入了一系列的组件通过List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);获取候选的配置,下一步通过SpringFactoriesLoader.loadFactoryNames() 扫描所有 jar 包类路径下的META-INF/spring.factories,将扫描到的文件内容包装成properties对象,从properties中获取到EnableAutoConfiguration.class类名对应的值,然后把他们添加到容器中。
将类路径下 META-INF/spring.factories 里面配置的 所有EnableAutoConfiguration的值添加到容器中
一下就是该文件中的一部分代码:
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,等等一些列的类
每一个这样的 XXXXAutoConfiguration类都是容器中的一个组件,都加入到容器中,用他们来自动配置
3).每个自动配置类@EnableAutoConfiguration进行自动配置功能
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; /** * Exclude specific auto-configuration classes such that they will never be applied. * @return the classes to exclude */ Class<?>[] exclude() default {}; /** * Exclude specific auto-configuration class names such that they will never be * applied. * @return the class names to exclude * @since 1.3.0 */ String[] excludeName() default {}; }
@AutoConfigurationPackage:自动配置包
@Import(AutoConfigurationPackages.Registrar.class)
spring的底层注解@Import,给容器导入一个组件()
AutoConfigurationPackages.Registrar.class:是将@SpringBootConfiguration 标注的类所在的包下的子包里面所有的组建扫描到spring容器中。
@Import(AutoConfigurationImportSelector.class):导入组件;
将所有需要导入的组件以全类名的方式返回:这些组件就会被添加到容器中
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return StringUtils.toStringArray(configurations);
}
configurations:里面存储的数组信息就是需要spring自动配置的全类名。(XXX.AutoConfiguration)。
4).以HttpEncodingAutoConfiguration为例解释自动配置原理
@Configuration // 这是一个配置类 也可以给容器中添加组件 // 启用指定类的ConfigurationProperties功能 // 将配置文件中对应的值跟HttpEncodingProperties绑定,并将HttpEncodingProperties加入IOC容器中 @EnableConfigurationProperties(HttpEncodingProperties.class) // spring底层@Conditional注解,根据不同的条件。如果满足指定条件,整个配置类才生效 // 判断当前应用是否web应用 @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) // 判断当前项目有没有这个类CharacterEncodingFilter:MVC中乱码解决的过滤器 @ConditionalOnClass(CharacterEncodingFilter.class) // 判断配置文件中是否存在某个配置spring.http.encoding.enabled,如果不存在也是成立的 // 也会通过 matchIfMissing = true判断默认生效 @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration { private final HttpEncodingProperties properties; public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) { this.properties = properties; } @Bean @ConditionalOnMissingBean public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE)); return filter; }
根据当前不同的条件判断,决定当前配置类是否生效?
一旦配置类生效:这个配置类就会给容器中添加各种组件,组件的属性来源于对应的XXXProperties类中获取的,这些类的每一个属性都来源于配置文件。
5).所有配置文件中能配置的属性在 xxxProperties类中封装着,配置文件中能配什么,这里就有什 么,
//从配置文件中获取指定的值和bean的属性进行绑定
@ConfigurationProperties(prefix = "spring.http.encoding") public class HttpEncodingProperties {
。。。
}
1.spring boot启动会加载大量的自动配置类
2.我们看我们需要的功能spring boot 默认写好的自动配置类有没有Properties
3.我们看这个自动配置类中配置了那些组件,没有的话自己编写
4.给容器中自动配置类添加组件时候,会从prperties类中获取某些属性,我们就可以在配置文件中指定他的值
XXXAutoConfiguration自动配置类给容器中添加组件就会有对应的XXXProperties来封装配置文件中相关的属性
以上是关于spring boot 自动配置原理的主要内容,如果未能解决你的问题,请参考以下文章
[Spring Boot] 4. Spring Boot实现自动配置的原理
[Spring Boot] 4. Spring Boot实现自动配置的原理