关联文章:
SpringBoot源码解析三部曲(二)——SpringApplication实例化
SpringBoot源码解析三部曲(三)——运行流程
以2.2.6.RELEASE为例:
由图中可以看出,2.2.x.RELEASE版本由两个子模块构成:
Spring Boot自动配置运行原理如下图所示:
可以用一句话来描述整个过程:Spring Boot通过@EnableAutoConfiguration注解开启自动配置,加载spring.factories中注册的各种AutoConfiguration类,当某个AutoConfiguration类满足其注解@Conditional指定的生效条件(Starters提供的依赖、配置或Spring容器中是否存在某个Bean等)时,实例化该AutoConfiguration类中定义的Bean,并注入Spring容器,就可以完成依赖框架的自动配置。
简单介绍一下图中所示的组件:
@EnableAutoConfiguration:该注解有组合注解@SpringBootApplication引入,完成自动配置开启,扫描各个jar包下的spring.factories文件,并加载文件中注册的AutoConfiguration类等。
spring.factories:配置文件,位与jar包的META-INF目录下,按照指定格式注册了自动配置的AutoConfiguration类。spring.factories也可以包含其他类型待注册的类。该配置文件不仅存在于Spring Boot项目中,也可以存在于自定义的自动配置(或Starter)项目中。
AutoConfiguration类:自动配置类,代表了Spring Boot中一类以XXAutoConfiguration命名的自动配置类。其中定义了三方组件集成Spring所需初始化的Bean和条件。
@Conditional:条件注解及其衍生注解,在AutoConfiguration类上使用,当满足该条件注解时才会实例化AutoConfiguration类。
Starters:三方组件的依赖及配置,Spring Boot已经预置的组件。Spring Boot默认的Starters项目往往只包含一个pom依赖的项目。如果是自定义的starter,该项目还需包含spring.factories文件、AutoConfiguration类和其他配置类。
@EnableAutoConfiguration是开启自动配置的注解,它是由@SpringBootApplication引入的。
Spring Boot项目会生成一个 xxxApplication的入口类,如下所示:
@SpringBootApplication
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}
该类的main方法用于启动Spring Boot项目的入口。唯一的注解@SpringBootApplication,用于开启自动配置,准确地说是通过该注解内的@EnableAutoApplication开启了自动配置。
@SpringBootApplication源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// 排除指定自动配置类
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
// 排除指定自动配置类名
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
// 指定扫描的基础包,激活注解组件的初始化
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
// 指定扫描的类,用于初始化
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
// 指定是否代理@Bean方法以强制执行bean的生命周期行为
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
该注解组合了@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan。@SpringBootConfiguration继承自@Configuration,用于标注当前类是配置类,将当前类中声明的一个或多个以@Bean注解标记的方法的实例装配到Spring容器中。@ComponentScan用于根据定义的扫描路径,把符合扫描规则的类装配到Spring容器中。
该注解提供了一下成员属性:
exclude:根据类(Class)排除指定的自动配置,该成员属性覆盖了@SpringBootApplication中组合的@EnableAutoConfiguration中定义的exclude成员属性。
excludeName:根据类名排除指定的自动配置,覆盖了@EnableAutoConfiguration中的excludeName的成员属性。
scanBasePackages:指定扫描的基础package,用于激活@Component等注解类的初始化。
scanBasePackageClasses:扫描指定的类,用于组件的初始化。
proxyBeanMethods:指定是否代理@Bean方法以强制执行bean的生命周期行为。此功能需要通过运行时生成CGLIB子类来实现方法拦截。
该注解中还大量使用@AliasFor注解,该注解用于桥接到其他注解,该注解的属性指定了所桥接的注解类。这些属性在其他注解中已经定义过了,之所以使用@AliasFor注解并重新在@SpringBootApplication中定义,更多是为了减少用户使用多注解带来的麻烦。
未使用Spring Boot的情况下,Bean的生命周期由Spring来管理,然而Spring无法自动配置@Configuration注解的类,Spring Boot的核心功能之一就是根据约定自动管理该注解标注的类。@EnableAutoConfiguration的主要功能是启动Spring应用程序上下文时进行自动配置,它会尝试猜测并配置项目可能需要的Bean。自动配置通常是基于项目classpath中引入的类和已定义的Bean来实现的。
@EnableAutoConfiguration注解源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
// 用于覆盖配置开启或关闭自动配置的功能
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
// 根据类(Class)排除指定的自动配置
Class<?>[] exclude() default {};
// 根据类名排除指定的自动配置
String[] excludeName() default {};
}
@EnableAutoConfiguration会猜测需要使用的Bean,但如果在项目中并不需要它预置初始化的Bean,可通过该注解的exclude或excludeName参数进行有针对性的排除。比如当不需要数据库自动配置时,可通过以下方式排除:
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class SpringBootDemoApplication {
}
@EnableAutoConfiguration的关键功能是通过@Import注解导入的ImportSelector接口来完成的,@Import(AutoConfigurationImportSelector.class)是自动配置功能的核心实现。
@Import注解主要提供导入配置类的功能,通过@Import可以引入@Configuration注解的类,也可以导入实现了ImportSelector接口或ImportBeanDefinitionRegistrar的类。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
Class<?>[] value();
}
@Import的功能基本都需要借助ImportSelector接口来实现,ImportSelector接口决定可引入哪些@Configuration。ImportSelector是Spring中的接口,源码如下:
public interface ImportSelector {
String[] selectImports(AnnotationMetadata var1);
@Nullable
default Predicate<String> getExclusionFilter() {
return null;
}
}
ImportSelector接口只提供了一个参数为AnnotationMetadata的方法,返回的结果为一个字符串数组。其中参数AnnotationMetadata内包含了被@Import注解的类的注解信息。在selectImports方法内可根据具体实现决定返回哪些配置类的全限定名,将结果以字符串数组的形式返回。
AutoConfigurationImportSelector部分源码如下:
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
}
AutoConfigurationImportSelector并没有直接实现了ImportSelector接口,而是实现了它的子接口DeferredImportSelector,DeferredImportSelector会在所有的@Configuration类加载完成之后再加载返回的配置类,而ImportSelector是在加载完@Configuration类之前先去加载返回的配置类。
AutoConfigurationImportSelector还实现了BeanClassLoaderAware、ResourceLoaderAware、BeanFactoryAware、EnvironmentAware,Spring会保证在调用ImportSelector之前会先调用Aware接口的方法。
AutoConfigurationImportSelector的核心功能和流程图如下:
当AutoConfigurationImportSelector被@Import注解引入之后,它的selectImports方法会被调用并执行其实现的自动装配逻辑。读者朋友需注意,selectImports方法几乎涵盖了组件自动装配的所有处理逻辑。源码如下:
/**
* AnnotationMetadata包含了被@Import注解的类的注解信息
* 返回值为配置类的全限定名字符串数组
*/
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 检查自动配置功能是否开启,默认为开启
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 加载自动配置的元信息,配置文件为类路径中META-INF目录下的spring-autoconfigure-metadata.properties文件
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
// 封装将被引入的自动配置信息
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
// 返回符合条件的配置类的全限定名数组
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
该方法用来检查自动配置功能是否开启,默认为开启状态
/**
* 判断是否开启自动配置功能
*/
protected boolean isEnabled(AnnotationMetadata metadata) {
/**
* 如果当前类为AutoConfigurationImportSelector, 程序会从环境中获取key为EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY的配置,
* 该常量的值为spring.boot.enableautoconfiguration. 如果获取不到该属性的配置, 返回默认值true, 也就是默认会使用自动配置
*/
if (getClass() == AutoConfigurationImportSelector.class) {
return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
}
// 如果当前类为其他类, 直接返回ture
return true;
}
从代码中可以看出,默认是会使用自动配置的。如果想覆盖或重置EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY的配置, 可在application.properties或application.yml中针对参数spring.boot.enableautoconfiguration进行配置,如在application.properties配置关闭自动配置, 则设置
spring.boot.enableautoconfiguration=false。
该方法会加载自动配置的元数据信息,使用的是AutoConfigurationMetadataLoader,从类名可以看出,是自动配置元数据加载器。
// 自动配置元数据加载
final class AutoConfigurationMetadataLoader {
// 默认加载元数据的路径
protected static final String PATH = "META-INF/spring-autoconfigure-metadata.properties";
private AutoConfigurationMetadataLoader() {
}
// 加载元数据, 默认加载PATH(即类路径下META-INF/spring-autoconfigure-metadata.properties)中的配置
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
return loadMetadata(classLoader, PATH);
}
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
try {
// 获取数据并且存储于Enumeration中
Enumeration<URL> urls = (classLoader != null) ? classLoader.getResources(path)
: ClassLoader.getSystemResources(path);
Properties properties = new Properties();
while (urls.hasMoreElements()) {
// 遍历Enumeration中的URL, 加载其中的属性, 存储到Properties
properties.putAll(PropertiesLoaderUtils.loadProperties(new UrlResource(urls.nextElement())));
}
return loadMetadata(properties);
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load @ConditionalOnClass location [" + path + "]", ex);
}
}
// 创建AutoConfigurationMetadata的实现类PropertiesAutoConfigurationMetadata
static AutoConfigurationMetadata loadMetadata(Properties properties) {
return new PropertiesAutoConfigurationMetadata(properties);
}
// AutoConfigurationMetadata的内部实现类
private static class PropertiesAutoConfigurationMetadata implements AutoConfigurationMetadata {
...
}
}
在上述代码中,AutoConfigurationMetadataLoader调用loadMetadata方法,获取默认变量PATH指定的文件,然后加载并存储在Enumeration数据机构中。随后,从文件中获取其中配置的数据存储于Properties内,最终调用在该类内部实现的AutoConfigurationMetadata的子类的构造方法。
spring-autoconfigure-metadata.properties文件内的配置格式如下:
自动配置类的全限定名.注解名称=值(如果文件内有多个值, 就用英文逗号隔开)
加载元数据是为了后续的过滤自动配置使用,Spring Boot使用一个Annotation的处理器来收集自动加载的条件,这些条件可以在元数据文件进行配置。Spring Boot会将收集好的@Configuration进行一次性过滤, 进而剔除不满足条件的配置类。官方文档显示,使用这种配置方式可以有效缩短Spring Boot的启动时间,减少@Configuration类的数量,从而减少初始化Bean的耗时。由于这块笔者还未接触到这块优化,对这个解释暂不清楚。
该方法用于封装将要引入的自动配置信息,也是自动配置的核心。
/**
* 封装将要引入的自动配置信息
*/
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
// 再次检查自动配置功能是否开启
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 获取自动装配元数据信息的属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 通过SpringFactoriesLoader类提供的方法加载类路径中META-INF目录下的spring.factories文件中针对EnableAutoConfiguration的注册配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 对获得的注册配置类集合进行去重处理,防止多个项目引入同样的配置类
configurations = removeDuplicates(configurations);
// 获取注解中被exclude或excludeName锁排除的类的集合
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
// 检查被排除类是否可实例化,是否被自动注册配置所使用,不符合条件则抛出异常
checkExcludedClasses(configurations, exclusions);
// 从自动配置类集合中去除被排除的类
configurations.removeAll(exclusions);
// 检查配置类的注解是否符合spring.factories文件中AutoConfigurationImportFilter指定的注解检查条件
configurations = filter(configurations, autoConfigurationMetadata);
// 将筛选完成的配置类和排查的配置类构建为事件类,并传入监听器。监听器的配置在spring.factories文件中,通过AutoConfigurationImportListener指定
// 并将事件类进行广播
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
该方法会获取注解@EnableAutoConfiguration上的属性,用于后续排除部分组件。
protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
// 获取注解@EnableAutoConfiguration的类名
String name = getAnnotationClass().getName();
// 获取注解@EnableAutoConfiguration上的属性
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(name, true));
Assert.notNull(attributes, () -> "No auto-configuration attributes found. Is " + metadata.getClassName()
+ " annotated with " + ClassUtils.getShortName(name) + "?");
return attributes;
}
protected Class<?> getAnnotationClass() {
return EnableAutoConfiguration.class;
}
自动配置组件在类路径中META-INF目录下的spring.factories文件中进行注册,getCandidateConfigurations方法通过Spring Core提供的SpringFactoriesLoader类可以读取spring.factories文件中注册的类。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// loadFactoryNames会读取META-INF/spring.factories中的配置
// 由于第一个参数为EnableAutoConfiguration.class,则只会读取配置文件中针对自动配置的注册类
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;
}
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
SpringFactoriesLoader中loadFactoryNames方法部分代码:
public final class SpringFactoriesLoader {
// 该类加载文件的路径,可能存在多个
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
...
// 加载所有的META-INF/spring.factories文件,封装成Map,并根据指定类名进行筛选,获取特定的列表
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
// 加载所有的META-INF/spring.factories文件,封装成Map,Key为接口的全类名,Value为对应配置值的List集合
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
...
}
spring.factories文件中EnableAutoConfiguration配置的部分内容如下图所示:
由于程序默认加载的是ClassLoader下面的所有META-INF/spring.factories文件中的配置,所以难免在不同的jar包中出现重复的配置,则需要进行去重操作。
去重很简单,通过Set集合去重。
protected final <T> List<T> removeDuplicates(List<T> list) {
return new ArrayList<>(new LinkedHashSet<>(list));
}
前面介绍过可以通过配置@EnableAutoConfiguration的注解属性exclude或excludeName进行排除指定组件。
protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
Set<String> excluded = new LinkedHashSet<>();
// 获取@EableAutoConfiguration注解中配置的exclude属性值
excluded.addAll(asList(attributes, "exclude"));
// 获取注解中配置的excludeName属性值
excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
// 获取配置文件中key为spring.autoconfigure.exclude的配置值
excluded.addAll(getExcludeAutoConfigurationsProperty());
return excluded;
}
private List<String> getExcludeAutoConfigurationsProperty() {
if (getEnvironment() instanceof ConfigurableEnvironment) {
Binder binder = Binder.get(getEnvironment());
// PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE的值为spring.autoconfigure.exclude
return binder.bind(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class).map(Arrays::asList)
.orElse(Collections.emptyList());
}
String[] excludes = getEnvironment().getProperty(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class);
return (excludes != null) ? Arrays.asList(excludes) : Collections.emptyList();
}
private void checkExcludedClasses(List<String> configurations, Set<String> exclusions) {
// 有问题的排除类集合
List<String> invalidExcludes = new ArrayList<>(exclusions.size());
// 遍历并判断是否存在对应的配置类
for (String exclusion : exclusions) {
if (ClassUtils.isPresent(exclusion, getClass().getClassLoader()) && !configurations.contains(exclusion)) {
invalidExcludes.add(exclusion);
}
}
// 如果不为空, 则进行处理
if (!invalidExcludes.isEmpty()) {
handleInvalidExcludes(invalidExcludes);
}
}
// 抛出异常
protected void handleInvalidExcludes(List<String> invalidExcludes) {
StringBuilder message = new StringBuilder();
for (String exclude : invalidExcludes) {
message.append("\t- ").append(exclude).append(String.format("%n"));
}
throw new IllegalStateException(String.format(
"The following classes could not be excluded because they are not auto-configuration classes:%n%s",
message));
}
checkExcludedClasses方法用来确保被排除的类存在于当前ClassLoader中,并且包含在spring.factories注册的集合中。如果不满足这些条件,调用handleInvalidExcludes方法抛出异常。
如果被排除的类符合条件,调用configurations.removeAll(exclusions)方法从自动配置集合中移除被排除类的集合,完成初步的自动配置组件排除。
/**
* 对自动配置类进行再次过滤
* configurations:经过初次过滤之后的自动配置组件列表
* autoConfigurationMetadata:元数据文件META-INF/spring-autoconfigure-metadata.properties中配置的实体类
*/
private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
long startTime = System.nanoTime();
// 候选自动配置组件
String[] candidates = StringUtils.toStringArray(configurations);
boolean[] skip = new boolean[candidates.length];
boolean skipped = false;
// 遍历过滤器集合
for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {
// 判断是否为Aware的相关子类
invokeAwareMethods(filter);
// 调用match判断是否匹配,参数1为待过滤的自动配置类数组,参数2为自动配置的元数据信息。
// 返回的结果为匹配过滤后的结果布尔数组,数组的大小与待过滤的自动配置类数组一致,如果需要排除,则设置对应的值为false
boolean[] match = filter.match(candidates, autoConfigurationMetadata);
for (int i = 0; i < match.length; i++) {
// 如果不匹配,则该索引位置置为空并设置跳过
if (!match[i]) {
skip[i] = true;
candidates[i] = null;
skipped = true;
}
}
}
if (!skipped) {
return configurations;
}
List<String> result = new ArrayList<>(candidates.length);
// 将不跳过的自动配置组件生成新的集合返回
for (int i = 0; i < candidates.length; i++) {
if (!skip[i]) {
result.add(candidates[i]);
}
}
if (logger.isTraceEnabled()) {
int numberFiltered = configurations.size() - result.size();
logger.trace("Filtered " + numberFiltered + " auto configuration class in "
+ TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
}
return new ArrayList<>(result);
}
// 获取Filter列表
protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
// 跟前面类似,通过SpringFactoriesLoader的loadFactories方法加载文件META-INF/spring.factories中配置的key为AutoConfigurationImportFilter的过滤器
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
}
META-INF/spring.factories文件中相关过滤器如下:
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
简述该filter方法的过程为:对自动配置组件列表再次过滤,过滤条件为该列表中自动配置类的注解得包含在OnBeanCondition、OnClassCondition、OnWebApplicationCondition中指定的注解,依次包含@ConditionalOnBean、@ConditionalOnClass和@ConditionalOnWebApplication。
接口的match方法主要由其抽象子类FilteringSpringBootCondition实现,但是在实现时又定义了新的抽象方法getOutcomes。
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
ConditionEvaluationReport report = ConditionEvaluationReport.find(this.beanFactory);
// 进行匹配筛选,返回匹配结果
ConditionOutcome[] outcomes = getOutcomes(autoConfigurationClasses, autoConfigurationMetadata);
// 将匹配结果转换成布尔数组
boolean[] match = new boolean[outcomes.length];
for (int i = 0; i < outcomes.length; i++) {
match[i] = (outcomes[i] == null || outcomes[i].isMatch());
if (!match[i] && outcomes[i] != null) {
logOutcome(autoConfigurationClasses[i], outcomes[i]);
if (report != null) {
report.recordConditionEvaluation(autoConfigurationClasses[i], this, outcomes[i]);
}
}
}
return match;
}
// 过滤器核心功能,该方法由子类实现
protected abstract ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata);
protected final ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 如果有多个处理器,采用后台线程处理
if (Runtime.getRuntime().availableProcessors() > 1) {
return resolveOutcomesThreaded(autoConfigurationClasses, autoConfigurationMetadata);
}
else {
OutcomesResolver outcomesResolver = new StandardOutcomesResolver(autoConfigurationClasses, 0,
autoConfigurationClasses.length, autoConfigurationMetadata, getBeanClassLoader());
return outcomesResolver.resolveOutcomes();
}
}
在完成以上步骤的过滤、筛选后,获得了需要进行自动配置的类集合。在将该集合返回之前,需要对相关时间进行封装和广播。
private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
// 通过SpringFactoriesLoader提供的loadFactories方法将spring.factories中配置的接口AutoConfigurationImportListener的实现类加载出来
List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
if (!listeners.isEmpty()) {
// 将筛选出来的自动配置类集合和被排除的自动配置类集合封装成AutoConfigurationImportEvent事件对象
AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
for (AutoConfigurationImportListener listener : listeners) {
invokeAwareMethods(listener);
// 将这些事件对象通过监听器提供的onAutoConfigurationImportEvent方法对事件进行广播
listener.onAutoConfigurationImportEvent(event);
}
}
}
protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class, this.beanClassLoader);
}