ray(factoryClassNames)));
}
return result;
} catch (IOException var8) {
throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8);
}
}
自动配置类中的条件注解
接下来,我们在spring.factories文件中随便找一个自动配置类,来看看是怎样实现的。我查看了MongoDataAutoConfiguration的源码,发现它声明了@ConditionalOnClass注解,通过看该注解的源码后可以发现,这是一个组合了@Conditional的组合注解,它的条件类是OnClassCondition。
@Configuration
@ConditionalOnClass({Mongo.class, MongoTemplate.class})
@EnableConfigurationProperties({MongoProperties.class})
@AutoConfigureAfter({MongoAutoConfiguration.class})
public class MongoDataAutoConfiguration {
....
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({OnClassCondition.class})
public @interface ConditionalOnClass {
Class<?>[] value() default {};
String[] name() default {};
}
然后,我们开始看OnClassCondition的源码,发现它并没有直接实现Condition接口,只好往上找,发现它的父类SpringBootCondition实现了Condition接口。
class OnClassCondition extends SpringBootCondition implements AutoConfigurationImportFilter, BeanFactoryAware, BeanClassLoaderAware {
.....
}
public abstract class SpringBootCondition implements Condition {
private final Log logger = LogFactory.getLog(this.getClass());
public SpringBootCondition() {
}
public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String classOrMethodName = getClassOrMethodName(metadata);
try {
ConditionOutcome ex = this.getMatchOutcome(context, metadata);
this.logOutcome(classOrMethodName, ex);
this.recordeva luation(context, classOrMethodName, ex);
return ex.isMatch();
} catch (NoClassDefFoundError var5) {
throw new IllegalStateException("Could not eva luate condition on " + classOrMethodName + " due to " + var5.getMessage() + " not found. Make sure your own configuration does not rely on that class. This can also happen if you are @ComponentScanning a springframework package (e.g. if you put a @ComponentScan in the default package by mistake)", var5);
} catch (RuntimeException var6) {
throw new IllegalStateException("Error processing condition on " + this.getName(metadata), var6);
}
}
public abstract ConditionOutcome getMatchOutcome(ConditionContext var1, AnnotatedTypeMetadata var2);
}
SpringBootCondition实现的matches方法依赖于一个抽象方法this.getMatchOutcome(context, metadata),我们在它的子类OnClassCondition中可以找到这个方法的具体实现。
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ClassLoader classLoader = context.getClassLoader();
ConditionMessage matchMessage = ConditionMessage.empty();
// 找出所有ConditionalOnClass注解的属性
List onClasses = this.getCandidates(metadata, ConditionalOnClass.class);
List onMissingClasses;
if(onClasses != null) {
// 找出不在类路径中的类
onMissingClasses = this.getMatches(onClasses, OnClassCondition.MatchType.MISSING, classLoader);
// 如果存在不在类路径中的类,匹配失败
if(!onMissingClasses.isEmpty()) {
return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnClass.class, new Object[0]).didNotFind("required class", "required class