springboot自动装配源码深度解析

springboot在启动可以通过自动装配导入相关配置类组件,然后进一步实现相关功能,因此可以整合多数框架,现在我们来分析下springboot自动装配的原理。可以看到对主类使用的@SpringBootApplication上存在@EnableAutoConfiguration,而这个注解导入AutoConfigurationImportSelector组件,因此接下来需要分析AutoConfigurationImportSelector组件。

@EnableAutoConfiguration
public @interface SpringBootApplication {}

@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

我们都知道spring在启动时会先获取Bean的定义再对Bean进行实例化,而扫描类路径创建Bean定义是由PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法实现的,此时会调用BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法。创建spring应用上下文时会对AnnotationConfigServletWebServerApplicationContext类实例化,进而调用AnnotationConfigUtils#registerAnnotationConfigProcessors向容器注册ConfigurationClassPostProcessor的Bean定义。

		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

ConfigurationClassPostProcessor实现了postProcessBeanDefinitionRegistry方法,此时会被调用。中间经过一堆方法调用,最终到AutoConfigurationImportSelector$AutoConfigurationGroup#process(),此时会调用当前类的getAutoConfigurationEntry(),这时就会到spring.factories中读取EnableAutoConfiguration配置的自动装配类了,其实此时已经不是从spring.factories文件中获取了,spring在构造SpringApplication时会创建初始化器,此时会调用getSpringFactoriesInstances()向setInitializers()传参,就会去spring.factories读取配置类并缓存下来,这样可以减少文件的读写次数。

// AutoConfigurationImportSelector.java
	protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
        //从spring.factories文件中获取
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
        //根据OnBeanCondition、OnClassCondition、OnWebApplicationCondition过滤组件
		configurations = getConfigurationClassFilter().filter(configurations);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		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;
	}

总结下,springboot的自动装配其实就是通过触发钩子函数,到spring.factories中读取配置项的值获取自动配置类。有不对的地方请大神指出,欢迎大家一起讨论交流,共同进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值