springboot自动配置执行原理

springboot自动配置详解

最近在研究springboot,小有心得,在此记录一下,同大家分享,同时博文如有不妥之处,请各位大佬指出,小弟不胜感激!

springboot的启动类都需要使用@SpringBootApplication注解,这个注解用到了下面这些注解
在这里插入图片描述
实现自动配置的三个关键注解:@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan。其中@EnableAutoConfiguration最为关键,下面就让我们逐个解读这三个注解的作用。

一.@SpringBootConfiguration

@SpringBootConfiguration继承了@Configuration注解,所以主要作用是表示当前类为注解类
在这里插入图片描述
该类的主要功能是代替spring的XML文件配置形式,之前spring的xml配置文件的配置bean,注入bean如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-lazy-init="true">
<bean id="testService" class="..TestServiceImpl">
...
</bean>
</beans>

而用@Configuration的配置形式如下:

@Configuration
public class testConfiguration{
    @Bean
    public TestService testService(){
        return new TestServiceImpl();
    }
}

二.@ComponentScan

组件扫描,主要作用是自动发现和装配Bean,将bean装配到IOC容器中,也可以用value属性定义扫描范围
@ComponentScan(value = {"com.test"})
如果不定义@ComponentScan,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描,这也是我们为什么会把启动类放到root package的原因。

三.@EnableAutoConfiguration(重点)

看名字也能知道这个注解才是自动配置的关键。我们看下这个注解下的内容:
在这里插入图片描述
其中最为关键的两个注解:
@AutoConfigurationPackage 和 @Import({AutoConfigurationImportSelector.class})

1.@AutoConfigurationPackage

这个注解其实也继承了@Import注解,主要作用就是将主程序类所在包的路径作为扫描器的base-package,然后添加到容器中,之后可以被用作spring.factories配置文件的key,我们点进去看一下:
在这里插入图片描述
其中Registrar.Class内容如下:
在这里插入图片描述
registerBeanDefinitions方法的主要作用是扫描主配置类同级目录以及子包,并将相应的组件导入到springboot创建管理的容器中。

2.@Import({AutoConfigurationImportSelector.class})

这个注解的作用是将AutoConfigurationImportSelector这个类的实例注入到IOC容器中,我们着重看下这个类主要做了什么:

这里是引用
看AutoConfigurationImportSelector源码,里面有个getAutoConfigurationEntry方法, 这个方法的主要作用就是去加载项目外部的配置(内部配置主要通过@ComponentScan扫描加载),我们着重看一下:

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata
autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
	if (!this.isEnabled(annotationMetadata)) {
		return EMPTY_ENTRY;
	} else {
		AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
		//获取自动配置的类名集合
		List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
		//将自动配置的类名去重
		configurations = this.removeDuplicates(configurations);
		//获取需要去除的列名
		Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
		this.checkExcludedClasses(configurations, exclusions);
		//将自动配置类名集合里的无用类去除
		configurations.removeAll(exclusions);
		//过滤,autoConfigurationMetadata为过滤条件
		configurations = this.filter(configurations, autoConfigurationMetadata);
		//自动装配导入事件
		this.fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
	}
}

上面的代码注释详细介绍了每一步的操作,我们着重看第一个方法,看看他是如何获取需要自动配置的类名集合的,我们点进去:
在这里插入图片描述
主要方法就一个SpringFactoriesLoader.loadFactoryNames(),SpringFactoriesLoader类属于Spring框架私有的一种扩展方案,其主要功能就是从指定的配置文件
META-INF/spring.factories加载配置,来加载到需要自动配置的类的全限定名列表我,们再点进去看下:

在这里插入图片描述
我们再看下loadSpringFactories方法的源码:
在这里插入图片描述
大体流程如下:
1.在缓存中查找配置结合结果,如果找到直接返回
2.如果缓存没有找到,则通过classLoader.getResources(“META-INF/spring.factories”)直接获取文件,这里注意,路径是写死的,“META-INF/spring.factories”。其中spring.factories的文件格式如下:
在这里插入图片描述
3.解析Properties,并且用key,value形式存到LinkedMultiValueMap集合中
4.将结果存到缓存里
5.返回集合,结构为key:factoriesType(例:org.springframework.boot.autoconfigure.EnableAutoConfiguration),value为配置的全类名(例:org.springframework.boot.autoconfigure.aop.AopAutoConfiguration)

之后就是对自动配置的类名集合进行简单的处理,然后将这些配置都加载到当前SpringBoot创建并使用的IoC容器中。

springboot自动装配的大体流程就如下图所示:
在这里插入图片描述

***还有一点:springboot启动加载自动配置的方法,是直接调用的AutoConfigurationImportSelector类下的getAutoConfigurationEntry方法,并不是通过selectImports方法调用的getAutoConfigurationEntry,需要debug走源码的同学注意下,断点不要打在selectImports方法里。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值