深入解析SpringBoot自动装配原理,轻松掌握SpringBoot核心功能

自动装配是SpringBoot的核心功能,它将开发人员从Bean的繁复配置中解脱出来。那么SpringBoot具体起什么作用呢?以Spring MVC为例,不采用SpringBoot时,需要配置视图解析器,文件解析器,请求适配器等各种Bean,如果采用SpringBoot,则只需集成spring-boot-starter-web依赖模块即可。同样如果使用数据库,在非SpringBoot工程中,我们需要配置dataSource、sessionFactory、transactionManager等各种Bean。

本文将逐步解析SpringBoot自动装配原理,首先从@SpringBootApplication启动注解入手,然后逐层分析SpringBoot怎么利用注解实现Bean自动装配的。

注解@SpringBootApplication一般作用在启动类上,由三个重要的Annotation组成@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan,其中@SpringBootConfiguration实际上就是代表了一个配置类,相当于一个beans.xml文件,@ComponentScan的功能其实就是自动扫描并加载符合条件的组件或bean定义,最终将这些bean 定义加载到Spring IoC容器中,@EnableAutoConfiguration代表开启SpringBoot的自动装配。

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM,
				classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
	@AliasFor(annotation = EnableAutoConfiguration.class)
	Class<?>[] exclude() default {};

	@AliasFor(annotation = EnableAutoConfiguration.class)
	String[] excludeName() default {};
	//根据包路径扫描
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
	String[] scanBasePackages() default {};
	//直接根据 class 类扫描
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
	Class<?>[] scanBasePackageClasses() default {};
}

继续深入了解@EnableAutoConfiguration注解,其中最关键的要属@Import(EnableAutoConfigurationImportSelector.class),借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到SpringBoot创建的IoC容器。同时借助于Spring的一个工具类SpringFactoriesLoader,去实现@EnableAutoConfiguration注解自动配置。

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
	//按类型排除不需要自动装配的类
	Class<?>[] exclude() default {};
	//按名称排除不需要自动装配的类
	String[] excludeName() default {};
}

查看AutoConfigurationImportSelector源码,可以看出该类实现了很多的xxxAware和DeferredImportSelector,并且所有的Aware都优先于selectImports方法执行。

public class AutoConfigurationImportSelector
		implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
		BeanFactoryAware, EnvironmentAware, Ordered {
	......
	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}

		// 加载META-INF/spring-autoconfigure-metadata.properties文件
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
				autoConfigurationMetadata, annotationMetadata);
		
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

	protected AutoConfigurationEntry getAutoConfigurationEntry(
			AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		// 获取注解@EnableAutoConfiguration的属性及其值
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		// 查找classpath下所有的META-INF/spring.factories文件,并从中读取org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,将其封装成List<String>返回
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		// 对上一步返回的List<String> configurations中的元素去重、排序
		configurations = removeDuplicates(configurations);
		// 依据attributes中的属性值排除一些特定的类
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		// 对上一步中所得到的List<String> configurations进行过滤,过滤的依据是条件匹配
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		configurations = filter(configurations, autoConfigurationMetadata);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}

	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
				getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
		return configurations;
	}
	......
}

SpringFactoriesLoader属于Spring框架私有的一种扩展方案,主要功能就是从指定的配置文件META-INF/spring.factories中加载配置,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为查找的Key,获取对应的一组@Configuration类。

综合所述,@EnableAutoConfiguration作用就是从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的配置项,通过反射实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后将这些都汇总成为一个实例并加载到IOC容器中。

但并不是所有EnableutoConfiguration的功能配置类都会生效,Spring会从classpath中查找是否有该配置项的依赖类(也就是pom.xml必须有对应功能的依赖包),并且配置类里面注入了默认属性值类,功能类可以引用并赋默认值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值