装配 SpringBoot自动配置流程

源码分析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

  1. @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
  1. @SpringBootConfiguration 是SpringBoot替代@Configuration的注解,增加了自动找到配置的功能
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Configuration//表示这是一个配置类 通过其间接了解到 , @SpringBootApplication也是一个配置类/*** 用作Spring的标准@Configuration注解的替代,以便可以自动找到配置*/public @interface SpringBootConfiguration {}@EnableAutoConfiguration
  1. @EnableAutoConfiguration注解就是启动自动配置的关键注解,其内部使用了@import注解引入了一个AutoConfigurationImportSelector 自动配置类选择器
@AutoConfigurationPackage //自动配置所在包注解,通过basePackages指定配置所在的包或者通过basePackageClasses指定基本包类,如果未指定,会默认注册指定注解类所在的包//AutoConfigurationImportSelector自动配置选择器,实现了ImportSelector接口,重写了selectImports方法,自动配置的具体实现就在其内部进行//ImportSelector接口作用 :根据给定的选择条件(通常是一个或多个注解属性)确定应导入哪个配置类 。@Import(AutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration {}? 在其内部重写了selectImports方法,通过调用getAutoConfigurationEntry()方法根据传入的注解元数据,获取到自动配置类的实体 , 而后从实体中获取具体的配置信息,配置信息在实体内部是一个list集合,所以将其转化为String数组后返回 。
//为方便显示及理解,省略了该类实现的部分接口和具体的代码实现,需要了解可进入源码查看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集合,其继承了LinkedHashMapAnnotationAttributes attributes = getAttributes(annotationMetadata);//2. 通过getCandidateConfigurations()方法根据注解元数据和注解的属性信息 获取应该进行自动配置的类名,可以理解为自动配置候选项List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);//2.1 通过removeDuplicates()方法对自动配置的类名进行去重处理configurations = removeDuplicates(configurations);//3. 根据注解元数据和注解属性获取到需排除配置项Set<String> exclusions = getExclusions(annotationMetadata, attributes);//3.1检查是否有无效的排除类存在checkExcludedClasses(configurations, exclusions);//3.2从自动配置候选项中删除需要排除的配置项configurations.removeAll(exclusions);//4. 调用getConfigurationClassFilter()方法获取到获取配置的所有AutoConfigurationImportFilter的实现类(对spring.factories进行过滤的类),调用filter方法对配置文件进行筛?。?而后返回需要自动配置的类configurations = getConfigurationClassFilter().filter(configurations);//5. 根据spring.factories文件中的AutoConfigurationImportListener事件监听器发布并处理监听事件,最后根据多次过滤、判重返回配置类合集fireAutoConfigurationImportEvents(configurations, exclusions);//6. 创建一个新的配置实体ConfigurationEntry并返回,包含需要配置项configurations,和被排除配置项exclusionsreturn new AutoConfigurationEntry(configurations, exclusions); }

推荐阅读