SpringBoot 自动装配原理

本文深入解析了SpringBoot的@SpringBootApplication注解,它是@Configuration、@EnableAutoConfiguration和@ComponentScan的组合。@EnableAutoConfiguration启动自动配置机制,@Configuration允许添加额外的bean,@ComponentScan扫描@Component等注解的bean。在AutoConfigurationImportSelector类中,通过ImportSelector接口的selectImports方法获取并加载符合条件的自动配置类。整个过程涉及SpringFactoriesLoader加载META-INF/spring.factories中的配置。自动配置的核心在于根据条件判断哪些配置类生效。

SpringBoot 的核心注解 SpringBootApplication 。
可以把 @SpringBootApplication看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合。根据 SpringBoot 官网,这三个注解的作用分别是:

@EnableAutoConfiguration:启用 SpringBoot 的自动配置机制

@Configuration:允许在上下文中注册额外的 bean 或导入其他配置类

@ComponentScan: 扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描启动类所在的包下所有的类 ,可以自定义不扫描某些 bean。如下图所示,容器中将排除TypeExcludeFilter和AutoConfigurationExcludeFilter。

@EnableAutoConfiguration 是实现自动装配的重要注解
EnableAutoConfiguration 只是一个简单地注解,自动装配核心功能的实现实际是通过 AutoConfigurationImportSelector类。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage //作用:将main包下的所欲组件注册到容器中
@Import({AutoConfigurationImportSelector.class}) //加载自动装配类 xxxAutoconfiguration
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

接下来分析AutoConfigurationImportSelector 类到底做了什么?

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {

}

public interface DeferredImportSelector extends ImportSelector {

}

public interface ImportSelector {
    String[] selectImports(AnnotationMetadata var1);
}

AutoConfigurationImportSelector 类实现了 ImportSelector接口,也就实现了这个接口中的 selectImports方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中。

	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
	//判断自动装配开关是否打开
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		 //获取所有需要装配的bean
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
				annotationMetadata);//重点关注
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

getAutoConfigurationEntry方法调用链如下为:
getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);→getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes)→ SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass()→SpringFactoriesLoader.loadSpringFactories(classLoader)

接下来看下getAutoConfigurationEntry()的源码

	protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
		//判断自动装配开关是否打开。默认spring.boot.enableautoconfiguration=true,可在 application.properties 或 application.yml 中设置
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		//用于获取EnableAutoConfiguration注解中的 exclude 和 excludeName。
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		//获取需要自动装配的所有配置类,读取META-INF/spring.factories;configurations就是所有META-INF/spring.factories下XXXAutoConfiguration类
		//不光是这个依赖下的META-INF/spring.factories被读取到,所有 Spring Boot Starter 下的META-INF/spring.factories都会被读取到。
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		//@ConditionalOnXXX 中的所有条件都满足,该类才会生效。
		configurations = filter(configurations, autoConfigurationMetadata);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}

以上是SpringBoot自动装配的基本流程;
核心处理@Configuration部分如下:
1、创建context的时候加载 ConfigurationClassPostProcessor
2、prepared context的 load 加载主函数到bean定义中
3、refreshContext方法 invokeBeanFactoryPostProcessors 调用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
4、主类带有@Configuration doProcessConfigurationClass 进行处理这时候会加载imports注解中的类
接着处理imports导入的类,在AutoConfigurationImportSelector中 利用loadFactory spi技术加载EnableAutoConfiguration对应的类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值