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 自动配置原理的主要内容,如果未能解决你的问题,请参考以下文章

4Spring Boot 自动配置原理

[Spring Boot] 4. Spring Boot实现自动配置的原理

[Spring Boot] 4. Spring Boot实现自动配置的原理

Spring Boot实战源码解析Spring Boot自动配置原理

spring boot 2 - *自动配置原理*(续)

Spring boot 自动配置原理