Spring Boot实现自动配置源码解析
概述
自动配置为Spring Boot的一大特性,根据引入的Jar包情况,动态的生成一组Bean,接下来我们从源码层面看下Spring Boot是如何实现自动配置的。
@EnableAutoConfiguration
所有的Spring Boot项目都必定有一个@SpringBootApplication
注解,自动配置的入口也是该注解。
@SpringBootApplication注解是一个组合注解:
// SpringBootApplication.java
@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 {
本篇文章我们只关心自动配置,所以仅关注@EnableAutoConfiguration
注解即可。
我们再看下@EnableAutoConfiguration
注解。
org.springframework.boot.autoconfigure.@EnableAutoConfiguration
注解,用于开启自动配置功能。
// EnableAutoConfiguration.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
@Import(AutoConfigurationImportSelector.class)
org.springframework.context.annotation.@Import
注解:用于资源的导入。AutoConfigurationImportSelector
:导入自动配置相关的资源。这是本文的重点。
AutoConfigurationImportSelector
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector
,实现 DeferredImportSelector
、BeanClassLoaderAware
、ResourceLoaderAware
、BeanFactoryAware
、EnvironmentAware
、Ordered
接口,处理 @EnableAutoConfiguration
注解的资源导入。
先看下自动配置类的基本加载过程,调用栈如下图所示:
- 由
ApplicationContext#refresh
作为入口开始加载自动配置类 - 仍然是Spring框架部分,提供了一种可扩展的导入配置类方式
AutoConfigurationImportSelector.AutoConfigurationGroup#process
作为Spring Boot的具体实现,加载META-INFO/spring.factories
下声明的EnableAutoConfiguration
自动配置类
Spring Boot从自动配置类加载BeanDefinition的完整流程如下:
既然,用户自定义的BeanDefinition在自动配置类加载之前已经进入BeanFactory,为什么不在
AutoConfigurationImportSelector#filter
阶段,既过滤自动配置类,又加载对应的BeanDefinition?而是在ConfigurationClassParser.DeferredImportSelectorGroupingHandler#processGroupImports
阶段做?
ConfigurationClassPostProcessor
// ConfigurationClassPostProcessor
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
......
//存放所有的BeanDefinitionHolder
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
//(\*\*)ConfigurationClassParser解析configCandidates中的配置类
//如果有@ComponentScan注解,扫描指定配置的所有配置类
//注册@Configuration类的BeanDefinition到BeanDefinitionRegistry
//1 ConfigurationClassParser.configurationClasses保存了所有的ConfigurationClass
parser.parse(candidates);
//校验ConfigurationClass的有效性
parser.validate();
//获取解析后的配置类
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
//移除已经解析的类
configClasses.removeAll(alreadyParsed);
// 通过ConfigurationClassBeanDefinitionReader加载BeanDefinition到BeanDefinitionRegistry
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// <2> (\*\*)扫描configClasses的所有配置类,@Bean方法为BeanDefinition,
// 条件注解@Conditional的判断也在这里生效
this.reader.loadBeanDefinitions(configClasses);
......
}
- 1 处
- 加载用户自定义BeanDefinition
- 加载Spring Boot自动配置类的入口,根据条件加载自动配置类
- 2处: 处理@Confiuration配置类,包括自动配置类,
- 执行完
ConfigurationClassParser#parse
即会加载Spring Boot的自动配置类,也会加载用户自定义的配置类。
ConfigurationClassParser
ConfigurationClassParser#doProcessConfigurationClass
:执行真正的配置类处理逻辑。根据当前配置类的注解,加载其它的BeanDefinition
。如:@Component
、@PropertySources
、@ComponentScans
、@ImportResource
等
#parse
// ConfigurationClassParser
public void parse(Set<BeanDefinitionHolder> configCandidates) {
// 从SpringApplication类加载Bean定义
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
// 1.加载SpringApplication扫描各种资源,包括@ComponentScan、@Import、@PropertySources、@Component等,可见`ConfigurationClassParser#doProcessConfigurationClass`
//(\*\*)用户自定义的配置类是在这里注册为BeanDefinition的
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
// 2.执行自动配置类的处理过程
this.deferredImportSelectorHandler.process();
}
- 很关键的点,用户自定义的BeanDefinition是在该处加载到BeanFactory,如
@Component
和@Configuration
- 开始加载Spring Boot的自动配置类
(**)#processGroupImports
- ConfigurationClassParser.DeferredImportSelectorGrouping#getImports:获取自动配置类,并做初次过滤,因为此时并没有用到BeanFactory,仅是根据过滤条件过滤一部分自动配置类
- ConfigurationClassParser#processImports:
- 根据@Conditional注解结合BeanFactory做二次过滤
- 处理配置类,
// ConfigurationClassParser
private class DeferredImportSelectorGroupingHandler {
.....
public void processGroupImports() {
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
grouping
// 1.导入自动配置类
.getImports()
.forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(
entry.getMetadata());
try {
// 2.处理自动配置类,
// @Conditional注解的二次过滤
// 根据配置类的注解加载BeanDefinition,如:`@Component`、`@PropertySources`、`@ComponentScans`、`@ImportResource`
processImports(configurationClass, asSourceClass(configurationClass),
asSourceClasses(entry.getImportClassName()), false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configurationClass.getMetadata().getClassName() + "]", ex);
}
});
}
}
......
- 1处:会导入自动配置类,并做初次过滤,过滤的入口为
FilteringSpringBootCondition#match
- 2处:处理自动配置类
- 对自动配置类做二次过滤,过滤的入口为
SpringBootCondition#match
- 通过自动配置类加载资源
- 对自动配置类做二次过滤,过滤的入口为
#getImports
// ConfigurationClassParser.DeferredImportSelectorGrouping
// 导入自动配置类
public Iterable<Group.Entry> getImports() {
//遍历DeferredImportSelectorHolder
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
//导入自动配置类,并做初次过滤
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
//返回当前Group的List<Entry>,实际上就是最终的导入的自动配置类
return this.group.selectImports();
}
group#process
:导入自动配置类,并做初次过滤。Spring Boot项目中的group
是AutoConfigurationSelector.AutoConfigurationGroup
,即调用了AutoConfigurationGroup#process
,加载符合条件的自动配置类(META-INFO/spring.factories
中指定的org.springframework.boot.autoconfigure.EnableAutoConfiguration
类)。group#selectImports
:排除无需导入的配置类,做排序,导入配置类
AutoConfigurationSelector.AutoConfigurationGroup
(**)AutoConfigurationGroup#process
获取符合条件的自动配置类。
private static class AutoConfigurationGroup implements DeferredImportSelector.Group,
BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware {
// AnnotationMetadata annotationMetadata:如@SpringBootApplication注解
@Override
public void process(AnnotationMetadata annotationMetadata,
DeferredImportSelector deferredImportSelector) {
//.....
//(\*\*)调用AutoConfigurationImportSelector获取AutoConfigurationEntry,主要包含符合条件的自动配置类
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(getAutoConfigurationMetadata(),
annotationMetadata);
//添加到autoConfigurationEntries
this.autoConfigurationEntries.add(autoConfigurationEntry);
//对每一个符合条件的配置类名称和注解信息保存到Map中
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
.......
}
#selectImports
// AutoConfigurationGroup
@Override
public Iterable<Entry> selectImports() {
if (this.autoConfigurationEntries.isEmpty()) {
return Collections.emptyList();
}
//得到所有要排除的自动配置类
Set<String> allExclusions = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getExclusions)
.flatMap(Collection::stream).collect(Collectors.toSet());
//得到所有符合条件的自动配置类
Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getConfigurations)
.flatMap(Collection::stream)
.collect(Collectors.toCollection(LinkedHashSet::new));
//移除需要排除的配置类
processedConfigurations.removeAll(allExclusions);
// 对标注有@Order自动配置类做排序
// 封装成List<Entry>,返回
// 1. @AutoConfigureOrder、@AutoConfigureBefore、@AutoConfigureAfter都在这里生效
return sortAutoConfigurations(processedConfigurations,
getAutoConfigurationMetadata())
.stream()
.map((importClassName) -> new Entry(
this.entries.get(importClassName), importClassName))
.collect(Collectors.toList());
}
- 1处:对自动配置类做排序,可见
@AutoConfigureOrder
、@AutoConfigureBefore
、@AutoConfigureAfter
,仅对自动配置类生效,也就是说,必须声明在META-INFO/spring.factories
中指定的org.springframework.boot.autoconfigure.EnableAutoConfiguration
类
(**)AutoConfigurationImportSelector —— 自动过滤的主体逻辑
封装了自动导入配置类的核心逻辑。
public class AutoConfigurationImportSelector
implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
BeanFactoryAware, EnvironmentAware, Ordered {
//......
/**
* 核心逻辑
*/
protected AutoConfigurationEntry getAutoConfigurationEntry(
AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
//是否启用自动配置
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//1. 获取所有的候选自动配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
//2.去除重复的自动配置类(通过Set实现)
configurations = removeDuplicates(configurations);
//从注解信息中获取排除的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
//排除exclude的配置类
configurations.removeAll(exclusions);
//3.(\*\*) 使用spring.factories中指定的AutoConfigurationImportFilter对自动配置类(configurations)过滤,这里实现类是FilteringSpringBootCondition
configurations = filter(configurations, autoConfigurationMetadata);
//4.调用`AutoConfigurationImportListener`发布自动配置类导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
//用AutoConfigurationEntry封装匹配的配置类和需要排除的配置类
return new AutoConfigurationEntry(configurations, exclusions);
}
}
- 加载所有的配置类
- 去除重复,去除exclusions中的配置类
- filter()过滤自动配置类,调用的
spring.factories
中指定的AutoConfigurationImportFilter
,过滤配置类 - 触发自动配置导入事件
getCandidateConfigurations —— 获取全部自动配置类
#getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes)
方法,加载在 META-INF/spring.factories
指定的全部 EnableAutoConfiguration
数组。代码如下:
// AutoConfigurationImportSelector.java
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// 1. 加载在 `META-INF/spring.factories` 指定的全部 `EnableAutoConfiguration`
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), //EnableAutoConfiguration.class
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;
}
-
1 处,调用
#getSpringFactoriesLoaderFactoryClass()
方法,返回指定类型为EnableAutoConfiguration
类。代码如下:// AutoConfigurationImportSelector.java protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }
-
1处,调用
SpringFactoriesLoader#loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader)
方法,加载META-INF/spring.factories
指定类型为EnableAutoConfiguration
的全部自动配置类
(**)filter —— 过滤自动配置类
这一层过滤并不是完整的过滤。如:在该阶段BeanFactory中并BeanDefinition,OnBeanCondition在该阶段无法判断BeanDefinition是否存在,仅判断对应的Bean的Class是否存在
// AutoConfigurationImportSelector
private List<String> filter(List<String> configurations,
AutoConfigurationMetadata autoConfigurationMetadata) {
long startTime = System.nanoTime();
//所有的配置类
String[] candidates = StringUtils.toStringArray(configurations);
//初始化skip数组,默认为false
boolean[] skip = new boolean[candidates.length];
boolean skipped = false;
// 获取META-INFO/spring.factories文件中,指定的`AutoConfigurationImportFilter`类数组
// 1. 基本的Spring Boot项目包括:OnClassCondition、OnWebApplicationCondition、OnBeanCondition
for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {
invokeAwareMethods(filter);
//2. AutoConfigurationImportFilter对所有的配置类匹配,得到匹配结果
boolean[] match = filter.match(candidates, autoConfigurationMetadata);
for (int i = 0; i < match.length; i++) {
//如果不匹配
if (!match[i]) {
//对应的skip设置为true
skip[i] = true;
//3. (\*\*)candidates数组中对应设置为空,即该自动配置类,无需参与下一轮的AutoConfigurationImportFilter#match
candidates[i] = null;
skipped = true;
}
}
}
//只要有一个不匹配,skipped就会为true,就不会直接返回所有的配置类
if (!skipped) {
return configurations;
}
List<String> result = new ArrayList<>(candidates.length);
for (int i = 0; i < candidates.length; i++) {
// skip==false,就添加到结果集里
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);
}
- 1处:说明Spring Boot内置支持的自动配置类由
OnClassCondition
、OnWebApplicationCondition
、OnBeanCondition
三个AutoConfigurationImportFilter
的实现类支持 - 2处:调用
AutoConfigurationImportFilter#match
匹配结果 - 3处:只要自动配置类有一个
AutoConfigurationImportFilter#match
的结果不匹配,就会直接被剔除,不会进入下一轮AutoConfigurationImportFilter#match
AutoConfigurationImportFilter ——自动配置类导入过滤器
AutoConfigurationImportFilter
注释:
"fast removal of auto-configuration classes before their bytecode is even read"
:做初次过滤,因为自动配置类可能会很多,如果无需使用,就没有必要加载自定的自动配置类。
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter
接口,用于过滤掉无需自动引入的自动配置类。
类图如下:
- AutoConfigurationImportFilter:实现了
AutoConfigurationImportFilter
的抽象基类 OnBeanCondition
,OnWebApplicationCondition
和OnClassCondition
都是AutoConfigurationImportFilter
的实现类
@FunctionalInterface
public interface AutoConfigurationImportFilter {
/**
* 过滤自动配置类
* @param autoConfigurationClasses 待过滤的自动配置类列表
* @param autoConfigurationMetadata 元数据信息
* @return 一个boolean数组,表示哪些自动配置类是匹配的
*/
boolean[] match(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata);
}
- 将传入的
autoConfigurationClasses
配置类们,根据autoConfigurationMetadata
的元数据(主要是注解信息),进行匹配,判断是否需要引入,然后返回的boolean[]
结果。 - 并且,
boolean[]
结果和autoConfigurationClasses
配置类们是一一对应的关系。假设autoConfigurationClasses[0]
对应的boolean[0]
为false
,表示无需引入,反之则需要引入。
FilteringSpringBootCondition
org.springframework.boot.autoconfigure.condition.FilteringSpringBootCondition
,继承 SpringBootCondition
抽象类,实现 AutoConfigurationImportFilter
、BeanFactoryAware
、BeanClassLoaderAware
接口。
- 具备
SpringBootCondition
的boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata)
过滤一般的@Conditional
修饰的@Configuration
配置类。在初次过滤的过程中,是不会涉及SpringBootCondition#matches
方法的。 - 具备
AutoConfigurationImportFilter
的boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata)
批量过滤META-INFO/spring.factories
指定的自动配置类
FilteringSpringBootCondition
的实现类有:
- OnWebApplicationCondition
- OnClassCondition
- OnBeanCondition
#match
abstract class FilteringSpringBootCondition extends SpringBootCondition
implements AutoConfigurationImportFilter, BeanFactoryAware, BeanClassLoaderAware {
// 仅仅是将`ConditionOutcome[] outcomes` -> `boolean[] match`,做一些记录
// 具体的逻辑由#getOutcomes实现
@Override
public boolean[] match(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
ConditionEvaluationReport report = ConditionEvaluationReport
.find(this.beanFactory);
//getOutcomes()是抽象方法,由子类实现
//对于每一个配置类都执行对应的getOutcomes()匹配,得到匹配结果,记录到ConditionOutcome数组中
ConditionOutcome[] outcomes = getOutcomes(autoConfigurationClasses,
autoConfigurationMetadata);
//记录匹配结果
boolean[] match = new boolean[outcomes.length];
for (int i = 0; i < outcomes.length; i++) {
//匹配成功的条件:outcomes[i]== null或者outcomes[i].isMatch==true
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);
}
FilteringSpringBootCondition#ClassNameFilter
ClassNameFilter是FilteringSpringBootCondition的内部枚举,用于判断类加载器是否能加载指定的类名。
// FilteringSpringBootCondition
protected enum ClassNameFilter {
// 如果类加载器加载类成功,即匹配
PRESENT {
@Override
public boolean matches(String className, ClassLoader classLoader) {
return isPresent(className, classLoader);
}
},
// 如果类加载器加载类失败,即匹配
MISSING {
@Override
public boolean matches(String className, ClassLoader classLoader) {
return !isPresent(className, classLoader);
}
};
abstract boolean matches(String className, ClassLoader classLoader);
static boolean isPresent(String className, ClassLoader classLoader) {
// 设置默认类加载器
if (classLoader == null) {
classLoader = ClassUtils.getDefaultClassLoader();
}
try {
// 尝试加载类,加载成功返回true
resolve(className, classLoader);
return true;
}
catch (Throwable ex) {
return false;
}
}
}
- 从这里可以看到
OnBeanCondition
在匹配自动配置类时,仅加载类,并没有通过BeanDefinition判断Bean是否存在BeanFactory中
OnBeanCondition
可用于调试的配置类
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration
- org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration
OnBeanCondition#getOutcomes
// OnBeanCondition
// 由FilteringSpringBootCondition的match进入
// autoConfigurationClasses:这里一些配置类在前几轮未能匹配成功,已经被设置为null
@Override
protected final ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
//用于保存每个Condition的匹配结果
ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
for (int i = 0; i < outcomes.length; i++) {
String autoConfigurationClass = autoConfigurationClasses[i];
if (autoConfigurationClass != null) {
//获取@ConditionalOnBean指定的Class[]
Set<String> onBeanTypes = autoConfigurationMetadata
.getSet(autoConfigurationClass, "ConditionalOnBean");
//匹配Bean是否存在
outcomes[i] = getOutcome(onBeanTypes, ConditionalOnBean.class);
//outcomes[i]==null表示匹配成功,进行@ConditionalOnSingleCandidate注解的匹配
if (outcomes[i] == null) {
//获取@ConditionalOnSingleCandidate指定的Class[]
Set<String> onSingleCandidateTypes = autoConfigurationMetadata.getSet(
autoConfigurationClass, "ConditionalOnSingleCandidate");
outcomes[i] = getOutcome(onSingleCandidateTypes,
ConditionalOnSingleCandidate.class);
}
}
}
return outcomes;
}
OnBeanCondition#getOutcome
// OnBeanCondition
private ConditionOutcome getOutcome(Set<String> requiredBeanTypes, Class<? extends Annotation> annotation) {
// 获取类加载器加载失败的类名称
List<String> missing = filter(requiredBeanTypes, ClassNameFilter.MISSING, getBeanClassLoader());
if (!missing.isEmpty()) {
// 生成匹配失败的消息
ConditionMessage message = ConditionMessage.forCondition(annotation)
.didNotFind("required type", "required types").items(Style.QUOTE, missing);
// 返回匹配失败的结果
return ConditionOutcome.noMatch(message);
}
// 返回null,即匹配成功了
return null;
}
FilteringSpringBootCondition#filter
//FilteringSpringBootCondition
protected final List<String> filter(Collection<String> classNames, ClassNameFilter classNameFilter,
ClassLoader classLoader) {
// 类名称列表为空,直接返回空列表
if (CollectionUtils.isEmpty(classNames)) {
return Collections.emptyList();
}
List<String> matches = new ArrayList<>(classNames.size());
// 遍历类名称列表,用ClassNameFilter#match匹配,匹配的添加到matches数组
for (String candidate : classNames) {
if (classNameFilter.matches(candidate, classLoader)) {
matches.add(candidate);
}
}
return matches;
}
OnBeanCondition为什么仅做类是否存在的判断?
- 为什么OnBeanCondition都没有对BeanDefinition做判断,而是直接类是否存在做判断?
- 在该阶段判断@ConditionalOnBean指定的Bean的类型是否存在,来过滤配置类,目的是减少加载进内存自动配置类的数量。
- 之后,处理自动配置类,会再次进入
OnBeanCondition#getMatchOutcome
过滤
其它Condition
OnWebApplicationCondition
和OnClassCondition
就不介绍了,感兴趣的朋友可以打断点调试一下,入口都是FilteringSpringBootCondition#match
方法
转载自:https://juejin.cn/post/7271576714693148687