SpringBoot 自动配置原理(三)
作者:互联网
上一篇文章中,我们提到AutoConfigurationImportSelector.AutoConfigurationGroup#process会将classpath下所有的META-INFO/spring.factories
中的org.springframework.boot.autoconfigure.EnableAutoConfiguration
属性中的自动配置类读取进来。spring.factories
中声明的自动装配类非常的多,难道我们每一个自动配置类都需要处理吗?答案当然是否定的,这篇文章来探讨一下SpringBoot是如何过滤掉不需要自动配置的类的。
AutoConfigurationImportSelector#getAutoConfigurationEntry
先来回顾一下方法getAutoConfigurationEntry
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//读取spring.factories中的自动配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
//读取@SpringBootApplication中excluded声明的要排除的自动配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//过滤不需要装配的自动配置类
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
这里的关键就在这个filter()方法中。
List<String> filter(List<String> configurations) {
long startTime = System.nanoTime();
String[] candidates = StringUtils.toStringArray(configurations);
boolean skipped = false;
//这里的filters其实是对@Conditional系列注解进行判断
//这里进行断点的话可以发现filters中是三个类,OnClassCondition\OnBeanCondition\OnWebApplicationCondition
for (AutoConfigurationImportFilter filter : this.filters) {
boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
for (int i = 0; i < match.length; i++) {
if (!match[i]) {
candidates[i] = null;
skipped = true;
}
}
}
if (!skipped) {
return configurations;
}
List<String> result = new ArrayList<>(candidates.length);
for (String candidate : candidates) {
if (candidate != null) {
result.add(candidate);
}
}
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 result;
}
@Conditional
我们任意点进一个spring.factories中的自动配置类,我们或多或少的可以看到如@ConditionalOnClass这样的注解,上面讲到的filter()方法就会对这些@Conditional注解进行过滤。这里简单介绍几个常见的@Conditional注解
-
@ConditionalOnClass
这个注解用于判断某个类是否存在于classpath中,如果存在则进行自动配置。
-
@ConditionalOnBean
这个注解用于判断某个Bean是否存在于IoC容器中,如果存在则进行自动配置。
-
@ConditionalOnMissingClass
这个注解用于判断某个类是否存在于classpath中,如果不存在则进行自动配置。
-
@ConditionalOnMissingBean
这个注解用于判断某个Bean是否存在于IoC容器中,如果不存在则进行自动配置。
经过过滤之后SpringBoot就会得到一个确定需要自动配置的类的全限定类名列表,之后的工作就交给Spring来完成了。
总结
spring.factories中的自动配置类并不是都需要自动配置,会通过在类上标注@Conditional注解的方式来告诉SpringBoot哪些类满足自动配置的需求,最后将经过过滤的自动配置类交给Spring来解析。
标签:SpringBoot,配置,filter,自动,注解,原理,candidates,configurations 来源: https://www.cnblogs.com/supermaskv/p/14988658.html