Spring自动配置流程及原理

属性配置官网:https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#common-application-properties

原理

@SpringBootApplication

spring主类必备注解,自动配置应该和它有关
点进@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 {

@EnableAutoConfiguration

发现里面有个@EnableAutoConfiguration注解(见名知义,启动自动配置),点进去

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

@Import

又是派生注解,里面有一个注解@Import,指定了一个自动配置导入选择器AutoConfigurationImportSelector
下面研究一下这个自动配置选择器AutoConfigurationImportSelector类,有一个重写的selectImports 方法

	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		// 获取自动配置项
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
				autoConfigurationMetadata, annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}
  1. 点进getAutoConfigurationEntry 方法(根据名字推断是获取自动配置项)
	/**
	 * Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
	 * of the importing {@link Configuration @Configuration} class.
	 * @param autoConfigurationMetadata the auto-configuration metadata
	 * @param annotationMetadata the annotation metadata of the configuration class
	 * @return the auto-configurations that should be imported
	 */
	protected AutoConfigurationEntry getAutoConfigurationEntry(
			AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		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 new AutoConfigurationEntry(configurations, exclusions);
	}

根据注释

Return the AutoConfigurationImportSelector.AutoConfigurationEntry
based on the AnnotationMetadata of the importing @Configuration class.

可以获知

基于标注@Configuration注解的配置类的注解元数据返回自动配置项

点进getCandidateConfigurations 方法(根据名字是获取配置)

	/**
	 * Return the auto-configuration class names that should be considered. By default
	 * this method will load candidates using {@link SpringFactoriesLoader} with
	 * {@link #getSpringFactoriesLoaderFactoryClass()}.
	 * @param metadata the source metadata
	 * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
	 * attributes}
	 * @return a list of candidate configurations
	 */
	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) {
		// 扫描 META-INF/spring.factories,获取自动配置类全限定名称
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
				getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
		Assert.notEmpty(configurations,
				"No auto configuration classes found in META-INF/spring.factories. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

根据注释

Return the auto-configuration class names that should be considered.
By default this method will load candidates using
SpringFactoriesLoader with getSpringFactoriesLoaderFactoryClass().

可以获知

是调用SpringFactoriesLoader.loadFactoryNames方法获取自动配置类全限定名称并返回结果

再根据代码

Assert.notEmpty(configurations,
				"No auto configuration classes found in META-INF/spring.factories. If you "
						+ "are using a custom packaging, make sure that file is correct.");

可以获知

自动配置类全限定名称是通过扫描 META-INF/spring.factories 获取

META-INF/spring.factories

查看 META-INF/spring.factories
在这里插入图片描述
可以发现文件内容格式是key = 用 “,” 隔开的value,如下

# 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,\

key: 启动自动配置类EnableAutoConfiguration的全类名org.springframework.boot.autoconfigure.EnableAutoConfiguration
value: 每个 “,” 分隔的都是一个自动配置类

流程

启动自动配置注解 @EnableAutoConfiguration 通过组合注解 @SpringBootApplication 标注在SpringBoot启动类上

@SpringBootApplication
public class Demo{

执行main方法,执行SpringApplication的run()方法

 public static void main(String[] args) {
        SpringApplication app = new SpringApplication(DistributeProceApp.class);
        Environment env = app.run(args).getEnvironment();
    }

内部执行selectImports() 方法,找到自动配置类的全限定名称,使用反射获取对应的class类,将所有配置类加载到Spring容器中,由此配置加载完成。

图示
请添加图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值