摘要
大家好,我是小编小八,好久不见,今天开始我将陆续分享我自己对springBoot的启动流程一些源码的理解,一共会分好几个篇章,大致目录就在下面啦,有什么说错的请各位jym批评指正哈!
目录一栏
- 启动注解
- 程序启动
- 环境准备
- 创建跟准备spring容器
- 刷新spring容器
这节我只讲注解的功能是什么,至于功能的具体实现我会在后面的章节里讲到
启动注解
SpringBoot启动必须要在main所在类上加这个注解\
@SpringBootApplication
他定义了spring扫描bean的范围、bean排除拦截器 同时它是多个功能注解的集合,主要包含了如下三个注解
@SpringBootConfiguration
这个注解目前没有实际的功能属性,继承了@Configuration注解也是一个配置类,主要作为一个springBoot配置标识
@ComponentScan
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
这个注解是spring框架中用于设置扫描bean扫描范围的,同时它也可以设置用于设置bean排除拦截器,这里就内置了两个拦截器
TypeExcludeFilter:用于获取bean工厂中设置的自定义TypeExcludeFilter,进行批量排除校验
AutoConfigurationExcludeFilter:用于排除掉一些配置了@Configuration注解但是已经在EnableAutoConfiguration集合中的class
@EnableAutoConfiguration
这个注解是springBoot进行做自动化配置的核心方法,点进去后发现他里面最核心就是@import注解,内置了如下两个类
AutoConfigurationImportSelector.class
设置的这个类继承了ImportSelector接口,主要的作用是会扫描所有jar包的META-INF目录下的spring.factories文件中的需要自动配置的configuration类全部获取出来,给到spring容器进行处理
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 是否需要进行自动配置
if (!isEnabled(annotationMetadata)) {
// 不需要,返回空数组
return NO_IMPORTS;
}
// 获取自动配置元数据,META-INF目录的spring-autoconfigure-metadata.properties文件
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
// 获取当前注解中的EnableAutoConfiguration注解信息
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 获取可选的配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
// 保持原顺序的去重,这个实现利用到了集合特性有兴趣的可以看看
configurations = removeDuplicates(configurations);
// 用排除拦截器过滤掉class
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 过滤一些被条件限制的配置,如:ConditionalOnClass、ConditionalOnMissingClass
configurations = filter(configurations, autoConfigurationMetadata);
// 触发自动配置类引入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return StringUtils.toStringArray(configurations);
}
获取可选的配置类具体实现
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
// 从META-INF目录的spring.factories文件获取key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的value值,根据,分成数组
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;
}
SpringFactoriesLoader.loadFactoryNames这个方法spring spi的核心入口,有兴趣的可以去了解下spring spi机制
AutoConfigurationPackages.Registrar.class
另一个import类,这个类继承了ImportBeanDefinitionRegistrar接口,这个类的作用是将启动类的包路径信息设置到BasePackages类中,这样spring就是自动将启动类目录及子目录都看作是扫描范围了
结束语
启动注解部分就简单的讲完啦,以上就是小编本人理解的实现原理,有些地方可能还是有点笼统,如果有疑问的,可以在评论区跟我讨论哈!!