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来封装配置文件中相关的属性

猜你喜欢

转载自www.cnblogs.com/wuzhenzhao/p/9151673.html