说起spring boot 大家首先能想到的就是方便,省去了SSM 那套繁琐的配置,而且容易出错,那么,我们有想过spring boot 是怎么做到自动配置的吗,这就离不开spring boot 读取自动配置类的原理,springboot 通过和spring整合做到了完美的自动启动,直接上代码
首先
我们进入这个注解看到
上面几个是元注解,我们平常自定义注解都有的
最主要是下面三个核心注解
@SpringBootConfiguration 该注解用来标记当前注解为springboot 自动配置类
@EnableAutoConfiguration 启动自动配置
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
用来指定扫面包,若不指定,则会默认扫描当前配置类所在的包
@Filter 指定排除某些类(配置类),避免我们自定义的类覆盖spring boot 中的Bean 导致读取不完整
我们进入@EnableAutoConfiguration
可以看到,该注解通过@Import 导入了一个Bean
(@Import 为spring 整合第三方框架常用注解,spring容器在启动时会自动解析标记了@Import 注解的Bean,并将其注册到BeanDefinitionMap 中),
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {.....}
可以看到该类实现了DeferredImportSelector
然后spring 会看该类是否重写了getImportGroup 方法
很显然,这类重写了getImportGroup 并且返回了一个AutoConfigurationGroup.class 类对象
继续点进入
程序会运行到这个方法,可以自己打断点跟一下
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
可以看到,这个理指定的key 是org.springframework.boot.enableautoconfigure
并且还会判断当前容器类型,默认就是servlet 类型的
可以看到,经过上个步骤的筛选,还剩42 个key-value
这其中就包括了jdbc,spirng web-mvc 、aop 等等
最后通过项目pom.xml 文件中引入的依赖最终去下载项目锁需要的依赖
上图为一个spring.factories 文件,容器启动过程会根据k-v 去筛选指定的key
最后读取项目所需要的依赖配置,完成读取配置类的流程
持续更新。。。