spring boot 读取启动配置类的流程、原理

说起spring boot 大家首先能想到的就是方便,省去了SSM 那套繁琐的配置,而且容易出错,那么,我们有想过spring boot 是怎么做到自动配置的吗,这就离不开spring boot 读取自动配置类的原理,springboot 通过和spring整合做到了完美的自动启动,直接上代码
首先
spring boot 读取启动配置类的流程、原理
我们进入这个注解看到
spring boot 读取启动配置类的流程、原理

上面几个是元注解,我们平常自定义注解都有的
最主要是下面三个核心注解
@SpringBootConfiguration 该注解用来标记当前注解为springboot 自动配置类
@EnableAutoConfiguration 启动自动配置
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
用来指定扫面包,若不指定,则会默认扫描当前配置类所在的包
@Filter 指定排除某些类(配置类),避免我们自定义的类覆盖spring boot 中的Bean 导致读取不完整

我们进入@EnableAutoConfiguration

spring boot 读取启动配置类的流程、原理
可以看到,该注解通过@Import 导入了一个Bean
(@Import 为spring 整合第三方框架常用注解,spring容器在启动时会自动解析标记了@Import 注解的Bean,并将其注册到BeanDefinitionMap 中),


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

可以看到该类实现了DeferredImportSelector
然后spring 会看该类是否重写了getImportGroup 方法

spring boot 读取启动配置类的流程、原理

很显然,这类重写了getImportGroup 并且返回了一个AutoConfigurationGroup.class 类对象
继续点进入

spring boot 读取启动配置类的流程、原理
程序会运行到这个方法,可以自己打断点跟一下

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		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());
		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;
	}

这里主要讲一下这个方法
List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());

这个方法就是通过读取依赖jar 包中的META-INFspring.factories 文件,根据key-value 读取指定key
spring boot 读取启动配置类的流程、原理
可以看到,这个理指定的key 是org.springframework.boot.enableautoconfigure
spring boot 读取启动配置类的流程、原理

并且还会判断当前容器类型,默认就是servlet 类型的
spring boot 读取启动配置类的流程、原理
可以看到,经过上个步骤的筛选,还剩42 个key-value
这其中就包括了jdbc,spirng web-mvc 、aop 等等
最后通过项目pom.xml 文件中引入的依赖最终去下载项目锁需要的依赖

spring boot 读取启动配置类的流程、原理
上图为一个spring.factories 文件,容器启动过程会根据k-v 去筛选指定的key

最后读取项目所需要的依赖配置,完成读取配置类的流程
持续更新。。。

上一篇:这篇带你深入理解SpringBoot中的自动装配


下一篇:初始化hive时报错:org.apache.hadoop.hive.metastore.HiveMetaException: Failed to get schema version