Springboot源码(二)@SpringBootApplication

@SpringBootApplication 注解流程解析

前言:上文已经分析了,springboot的入口函数的实现过程,如何启动 ioc容器,如何监听等等。
**本文继续分析第二部分,springboot中的@SpringbootApplication 注解如何实现的自动配置 **

废话少说上 @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 

我们逐个分析其中的注解:
**@ComponentScan** 是Spring 中的注解,默认扫描注解类的包路径不再多说了


**@SpringBootConfiguration**** **这个注解是springboot中的,我们看看这个注解的源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {

}

看完我们就很清楚了,熟悉的注解 @Configuration ** **这个作用我们也不在多说。用来标注配置类的。


**@EnableAutoConfiguration** 这是我们的主要实现注解,我们来看源码

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

看到 @import 注解导入了bean AutoConfigurationImportSelector.class 和@AutoConfigurationPackage
我们接下来分开看一看。

1.@Import(AutoConfigurationImportSelector.class)

我们看下 AutoConfigurationImportSelector 类的核心代码

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
        
         // 核心逻辑1  在spring扫描 configuration 类的时侯调用
         @Override
		public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
			// 获取自动配置类
			AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
					.getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
			this.autoConfigurationEntries.add(autoConfigurationEntry);
			for (String importClassName : autoConfigurationEntry.getConfigurations()) {
				this.entries.putIfAbsent(importClassName, annotationMetadata);
			}
		}
            
            
        //核心逻辑2  获取过滤后的自动配置类
        protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		// 1. 获取@SpringbootApplication注解信息
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		// 2. 获取 spring.factories 文件中的 EnableAutoConfiguration 类配置
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		// 3. 将配置类使用set去重
		configurations = removeDuplicates(configurations);
		// 4. 过滤掉需要排除的 配置类
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		// 5. 过滤器 过滤  AutoConfigurationImportFilter.class
		configurations = filter(configurations, autoConfigurationMetadata);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		// 返回自动配置类信息
		return new AutoConfigurationEntry(configurations, exclusions);
	}
 }

因为 实现了 DeferredImportSelector 类,所以在spring 扫描import组件的时侯会延迟等待其他扫描完成后执行
process方法。
看下 spring容器启动过程中ConfigurationClassParser#processImports 的源码

if (selector instanceof DeferredImportSelector) {
	this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}


总结:看到这里我们可以了解自动配置类是如何被发现的。通过扫描路径下的 “META-INF/spring.factories” 文件中 EnableAutoConfiguration.class 的对应配置,然后通过去重,排除,过滤几大步骤 ,然后会通过spring源码中的 ConfigurationClassPostProcessor 步骤 ,将定义信息进行注入ioc容器

// 将通过解析@Bean,@Import等注解得到相关信息解析成bd被注入到容器中
this.reader.loadBeanDefinitions(configClasses);

2.@AutoConfigurationPackage

这个组合注解主要是@Import(AutoConfigurationPackages.Registrar.class),它通过将Registrar类导入到容器中,而Registrar类作用是扫描主配置类同级目录以及子包,并将相应的组件导入到springboot创建管理的容器中;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值