源码分析
SpringBoot自动配置流程
?
? 首先,我们要了解在@SpringBootApplication注解的内部,还具有@EnableAutoConfiguration,@SpringBootConfiguration,@ComponentScan三个主要注解。
@SpringBootConfiguration //标注该类是配置类,需要通过该类查找自动配置文件
@EnableAutoConfiguration //自动配置的关键注解 其内部就是执行自动配置的代码
@ComponentScan(excludeFilters = {
//type : 要使用的筛选器类型 , classes 指定类型筛选器
//TypeExcludeFilter.class 筛选掉spirngBootApplication中被指定排除的配置类
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
//AutoConfigurationExcludeFilter 将配置类与spirng.factories中的EnableAutoConfiguration对应的配置类进行对比匹配, 如果一致,会被排除掉
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }
) //扫描指定包的文件,将带有特定注解的类注入到Bean中
public @interface SpringBootApplication {
}
@ComponentScan
- @ComponentScan注解主要用来扫描我们项目中的所有被像@service ,@Repository , @Controller,@configuration 等注解修饰的类, 将其注入到我们的IOC容器中,其中也包括我们的自动配置的文件:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class) //表示可以重复利用@ComponentScan注解
/**
*作用 : 可以扫描指定的包,如果未指定包范围,将从该注解标注类所在的包进行扫描,
* 与XML形式的<context:component scan>不同的是 @componentScan没有Config属性(true * 就开启了属性自动注入的功能,如果是false就是关闭属性自动注入的功能),因为使用
* @ComponentScan则默认所有的类都进行自动注入,会将所有扫描到的组件注入到IOC容器中
*/
public @interface ComponentScan {
}
@SpringBootConfiguration
- @SpringBootConfiguration 是SpringBoot替代@Configuration的注解,增加了自动找到配置的功能
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration //表示这是一个配置类 通过其间接了解到,@SpringBootApplication也是一个配置类
/**
* 用作Spring的标准@Configuration注解的替代,以便可以自动找到配置
*/
public @interface SpringBootConfiguration {
}
@EnableAutoConfiguration
- @EnableAutoConfiguration注解就是启动自动配置的关键注解,其内部使用了@import注解引入了一个AutoConfigurationImportSelector 自动配置类选择器
@AutoConfigurationPackage //自动配置所在包注解,通过basePackages指定配置所在的包或者通过basePackageClasses指定基本包类,如果未指定,会默认注册指定注解类所在的包
//AutoConfigurationImportSelector自动配置选择器,实现了ImportSelector接口,重写了selectImports方法,自动配置的具体实现就在其内部进行
//ImportSelector接口作用 :根据给定的选择条件(通常是一个或多个注解属性)确定应导入哪个配置类。
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
? 在其内部重写了selectImports方法, 通过调用getAutoConfigurationEntry()方法根据传入的注解元数据,获取到自动配置类的实体,而后从实体中获取具体的配置信息,配置信息在实体内部是一个list
//为方便显示及理解,省略了该类实现的部分接口和具体的代码实现,需要了解可进入源码查看
public class AutoConfigurationImportSelector implements DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//AnnotationMetadata: 配置类的注解元数据,也就是配置类的注解信息
//调用getAutoConfigurationEntry()方法根据传入的注解信息,获取并返回自动配置类的实体
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
//从配置实体中获取具体的配置信息,返回的是一个list集合,而后通过toStringArray()方法转存到字符串数组中返回
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
getAutoConfigurationEntry()
//可以先看下获取的大致流程,而后进入查看器方法内部的具体实现
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
//1. 从注解元数据中获取注解的相应属性,将相应属性存储到map中返回
//1.1AnnotationAttributes是一个Map集合,其继承了LinkedHashMap
AnnotationAttributes attributes = getAttributes(annotationMetadata