目录
AutoConfigurationImportFilter的使用
在AutoConfigurationImportSelector实现的selectImports方法中会通过AutoConfigurationImportFilter的相关接口实现来进行自动配置类的过滤
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;
//获取META-INF/spring.factories中配置的所有过滤器
Iterator var8 = this.getAutoConfigurationImportFilters().iterator();
//遍历所有过滤器,并执行其match方法
while(var8.hasNext()) {
AutoConfigurationImportFilter filter = (AutoConfigurationImportFilter)var8.next();
this.invokeAwareMethods(filter);
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;
} else {
List<String> result = new ArrayList(candidates.length);
int numberFiltered;
for(numberFiltered = 0; numberFiltered < candidates.length; ++numberFiltered) {
if (!skip[numberFiltered]) {
result.add(candidates[numberFiltered]);
}
}
if (logger.isTraceEnabled()) {
numberFiltered = configurations.size() - result.size();
logger.trace("Filtered " + numberFiltered + " auto configuration class in " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
}
return new ArrayList(result);
}
}
protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
}
AutoConfigurationImportFilter过滤基本流程
- 获取META-INF/spring.factories中配置的所有过滤器
- 遍历所有过滤器,并执行其match方法
- 拼接自动配置类名和注解名为特定字符
- 根据字符串查询元数据中配置的类
- 尝试用类加载器加载该类
- 加载成功则匹配成功,抛出异常则匹配失败
1.获取META-INF/spring.factories中配置的所有过滤器
protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
}
通过loadFactories方法在META-INF/spring.factories中获取所有的筛选条件,包括:
- OnBeanCondition
- OnClassCondition
- OnWebApplicationCondition
2.遍历所有过滤器,并执行其match方法
遍历到的过滤器都实现了FilteringSpringBootCondition类,而FilteringSpringBootCondition则实现了AutoConfigurationImportFilter类,其中的match方法用来判断条件是否符合,match方法的实现方法如下:
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
ConditionEvaluationReport report = ConditionEvaluationReport.find(this.beanFactory);
ConditionOutcome[] outcomes = this.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) {
this.logOutcome(autoConfigurationClasses[i], outcomes[i]);
if (report != null) {
report.recordConditionEvaluation(autoConfigurationClasses[i], this, outcomes[i]);
}
}
}
return match;
}
其中主要的判断逻辑,是在getOutcomes方法中,各过滤器实现了相应的getOutcomes方法用来进行条件判断。
3.拼接自动配置类名和注解名为特定字符
在各过滤器实现的getOutcomes方法中,对需要过滤的自动配置类进行分半处理,并且单独提取每一个自动配置类的条件进行判断,最后进行判断的步骤为:
private ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses, int start, int end, AutoConfigurationMetadata autoConfigurationMetadata) {
ConditionOutcome[] outcomes = new ConditionOutcome[end - start];
for(int i = start; i < end; ++i) {
String autoConfigurationClass = autoConfigurationClasses[i];
if (autoConfigurationClass != null) {
String candidates = autoConfigurationMetadata.get(autoConfigurationClass, "ConditionalOnClass");
if (candidates != null) {
outcomes[i - start] = this.getOutcome(candidates);
}
}
}
return outcomes;
}
private ConditionOutcome getOutcome(String candidates) {
try {
if (!candidates.contains(",")) {
return this.getOutcome(candidates, this.beanClassLoader);
}
String[] var2 = StringUtils.commaDelimitedListToStringArray(candidates);
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
String candidate = var2[var4];
ConditionOutcome outcome = this.getOutcome(candidate, this.beanClassLoader);
if (outcome != null) {
return outcome;
}
}
} catch (Exception var7) {
}
return null;
}
private ConditionOutcome getOutcome(String className, ClassLoader classLoader) {
return ClassNameFilter.MISSING.matches(className, classLoader) ? ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnClass.class, new Object[0]).didNotFind("required class").items(Style.QUOTE, new Object[]{className})) : null;
}
其中,通过PropertiesAutoConfigurationMetadata实现了AutoConfigurationMetadata的get方法,以拼接后的字符串作为key,从META-INF/spring-autoconfigure-metadata.properties文件中得到该条件对应的类:
public String get(String className, String key, String defaultValue) {
//拼接自动配置类名和注解名为特定字符
//根据字符串查询元数据中配置的类
String value = this.properties.getProperty(className + "." + key);
return value != null ? value : defaultValue;
}
4.根据字符串查询元数据中配置的类
5.尝试用类加载器加载该类
获得类名称之后,则采用ClassNameFilter.MISSING的matches方法进行判断:
protected static enum ClassNameFilter {
PRESENT {
public boolean matches(String className, ClassLoader classLoader) {
return isPresent(className, classLoader);
}
},
MISSING {
public boolean matches(String className, ClassLoader classLoader) {
return !isPresent(className, classLoader);
}
};
private ClassNameFilter() {
}
public abstract boolean matches(String className, ClassLoader classLoader);
public static boolean isPresent(String className, ClassLoader classLoader) {
if (classLoader == null) {
classLoader = ClassUtils.getDefaultClassLoader();
}
//加载成功则匹配成功,抛出异常则匹配失败
try {
forName(className, classLoader);
return true;
} catch (Throwable var3) {
return false;
}
}
//尝试用类加载器加载该类
private static Class<?> forName(String className, ClassLoader classLoader) throws ClassNotFoundException {
return classLoader != null ? classLoader.loadClass(className) : Class.forName(className);
}
}
6.加载成功则匹配成功,抛出异常则匹配失败
参考
(《Spring Boot 技术内幕》)