@ConditionalOnBean注解使用了@Condition注解,@Condition注解中使用的条件类是OnBeanCondition类,那就看下这个类。
在此之前,顺便先提一句,@ConditionalOnBean 是匹配目前为止由应用程序上下文处理过的bean定义,而不是 bean实例。bean实例还早的很。网上很多文章都写的是bean实例,误人子弟,后面源码会分析到。源码有些多,还请耐心看下去,如果实在看不下去,可看下此注解的注释,也有简单的说明。
OnBeanCondition类继承FilteringSpringBootCondition。
FilteringSpringBootCondition又继承SpringBootCondition。
SpringBootCondition的matches方法。
//SpringBootCondition类中的matches方法
public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//获取当前注解标记的类名或者方法名(由标注的位置决定)
String classOrMethodName = getClassOrMethodName(metadata);
try {
//关键代码:这里就会判断出结果
ConditionOutcome outcome = this.getMatchOutcome(context, metadata);
//存入日志
this.logOutcome(classOrMethodName, outcome);
//存入记录
this.recordEvaluation(context, classOrMethodName, outcome);
//最后返回ConditionOutcome的isMatch就是返回boolean类型结果
return outcome.isMatch();
} catch (NoClassDefFoundError var5) {
throw new IllegalStateException("Could not evaluate 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);
}
}
关键代码在OnBeanCondition的getMatchOutcome方法中。
/**
* 获得判断结果的方法,ConditionOutcome类中存着boolean类型的结果
*/
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
//返回一个新的ConditionMessage
ConditionMessage matchMessage = ConditionMessage.empty();
//这是metadata会调用isAnnotated方法判断当前标注的注解是不是ConditionalOnBean
if (metadata.isAnnotated(ConditionalOnBean.class.getName())) {
//返回一个spec(说明),这里的spec规定了搜索的内容,比如搜索策略、需要搜索的类名......
BeanSearchSpec spec = new BeanSearchSpec(context, metadata, ConditionalOnBean.class);
//主要的搜索实现在这个方法里
MatchResult matchResult = getMatchingBeans(context, spec);
//判断搜索出来的结果
if (!matchResult.isAllMatched()) {
String reason = createOnBeanNoMatchReason(matchResult);
return ConditionOutcome
.noMatch(ConditionMessage.forCondition(ConditionalOnBean.class, spec).because(reason));
}
matchMessage = matchMessage.andCondition(ConditionalOnBean.class, spec).found("bean", "beans")
.items(Style.QUOTE, matchResult.getNamesOfAllMatches());
}
//这是metadata会调用isAnnotated方法判断当前标注的注解是不是ConditionalOnSingleCandidate
if (metadata.isAnnotated(ConditionalOnSingleCandidate.class.getName())) {
BeanSearchSpec spec = new SingleCandidateBeanSearchSpec(context, metadata,
ConditionalOnSingleCandidate.class);
MatchResult matchResult = getMatchingBeans(context, spec);
if (!matchResult.isAllMatched()) {
return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnSingleCandidate.class, spec)
.didNotFind("any beans").atAll());
}
else if (!hasSingleAutowireCandidate(context.getBeanFactory(), matchResult.getNamesOfAllMatches(),
spec.getStrategy() == SearchStrategy.ALL)) {
return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnSingleCandidate.class, spec)
.didNotFind("a primary bean from beans")
.items(Style.QUOTE, matchResult.getNamesOfAllMatches()));
}
matchMessage = matchMessage.andCondition(ConditionalOnSingleCandidate.class, spec)
.found("a primary bean from beans").items(Style.QUOTE, matchResult.getNamesOfAllMatches());
}
//这是metadata会调用isAnnotated方法判断当前标注的注解是不是ConditionalOnMissingBean
if (metadata.isAnnotated(ConditionalOnMissingBean.class.getName())) {
BeanSearchSpec spec = new BeanSearchSpec(context, metadata, ConditionalOnMissingBean.class);
MatchResult matchResult = getMatchingBeans(context, spec);
if (matchResult.isAnyMatched()) {
String reason = createOnMissingBeanNoMatchReason(matchResult);
return ConditionOutcome
.noMatch(ConditionMessage.forCondition(ConditionalOnMissingBean.class, spec).because(reason));
}
matchMessage = matchMessage.andCondition(ConditionalOnMissingBean.class, spec).didNotFind("any beans")
.atAll();
}
return ConditionOutcome.match(matchMessage);
}
BeanSearchSpec spec = new OnBeanCondition.BeanSearchSpec(context, metadata, ConditionalOnBean.class);
相当于将标注@ConditionalOnMissingBean注解时的属性都取出来放到内部类BeanSearchSpec中。
public BeanSearchSpec(ConditionContext context, AnnotatedTypeMetadata metadata, Class<?> annotationType,
Class<?> genericContainer) {
this.annotationType = annotationType;
MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(annotationType.getName(),
true);
//注解的name属性
collect(attributes, "name", this.names);
//注解的value属性
collect(attributes, "value", this.types);
//注解的type属性
collect(attributes, "type", this.types);
collect(attributes, "annotation", this.annotations);
collect(attributes, "ignored", this.ignoredTypes);
collect(attributes, "ignoredType", this.ignoredTypes);
collect(attributes, "parameterizedContainer", this.parameterizedContainers);
this.strategy = (SearchStrategy) attributes.getFirst("search");
BeanTypeDeductionException deductionException = null;
try {
if (this.types.isEmpty() && this.names.isEmpty()) {
addDeducedBeanType(context, metadata, this.types);
}
}
catch (BeanTypeDeductionException ex) {
deductionException = ex;
}
validate(deductionException);
}
看主要的搜索实现方法 getMatchingBeans。
protected final MatchResult getMatchingBeans(ConditionContext context, BeanSearchSpec beans) {
//获得当前bean工厂
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//判断当前的搜索策略是否是PARENTS或者ANCESTORS,默认是ALL
if (beans.getStrategy() == SearchStrategy.ANCESTORS) {
BeanFactory parent = beanFactory.getParentBeanFactory();
Assert.isInstanceOf(ConfigurableListableBeanFactory.class, parent,
"Unable to use SearchStrategy.ANCESTORS");
//如果是PARENTS或者ANCESTORS,当前bean工厂就用父工厂
beanFactory = (ConfigurableListableBeanFactory) parent;
}
MatchResult matchResult = new MatchResult();
//如果当前搜索策略不等于CURRENT,为true
boolean considerHierarchy = beans.getStrategy() != SearchStrategy.CURRENT;
TypeExtractor typeExtractor = beans.getTypeExtractor(context.getClassLoader());
List<String> beansIgnoredByType = getNamesOfBeansIgnoredByType(beans.getIgnoredTypes(), typeExtractor,
beanFactory, context, considerHierarchy);
//注解的value和types都在types里面
for (String type : beans.getTypes()) {
//看 getBeanNamesForType 方法
Collection<String> typeMatches = getBeanNamesForType(beanFactory, type, typeExtractor,
context.getClassLoader(), considerHierarchy);
typeMatches.removeAll(beansIgnoredByType);
if (typeMatches.isEmpty()) {
matchResult.recordUnmatchedType(type);
}
else {
matchResult.recordMatchedType(type, typeMatches);
}
}
for (String annotation : beans.getAnnotations()) {
List<String> annotationMatches = Arrays.asList(
getBeanNamesForAnnotation(beanFactory, annotation, context.getClassLoader(), considerHierarchy));
annotationMatches.removeAll(beansIgnoredByType);
if (annotationMatches.isEmpty()) {
matchResult.recordUnmatchedAnnotation(annotation);
}
else {
matchResult.recordMatchedAnnotation(annotation, annotationMatches);
}
}
for (String beanName : beans.getNames()) {
if (!beansIgnoredByType.contains(beanName) && containsBean(beanFactory, beanName, considerHierarchy)) {
matchResult.recordMatchedName(beanName);
}
else {
matchResult.recordUnmatchedName(beanName);
}
}
return matchResult;
}
//根据类型获取bean的name
private Collection<String> getBeanNamesForType(ListableBeanFactory beanFactory, String type,
TypeExtractor typeExtractor, ClassLoader classLoader, boolean considerHierarchy) throws LinkageError {
try {
//继续看 getBeanNamesForType 方法
return getBeanNamesForType(beanFactory, considerHierarchy, ClassUtils.forName(type, classLoader),
typeExtractor);
}
catch (ClassNotFoundException | NoClassDefFoundError ex) {
return Collections.emptySet();
}
}
private Collection<String> getBeanNamesForType(ListableBeanFactory beanFactory, boolean considerHierarchy,
Class<?> type, TypeExtractor typeExtractor) {
Set<String> result = new LinkedHashSet<>();
//继续看 collectBeanNamesForType 方法
collectBeanNamesForType(result, beanFactory, type, typeExtractor, considerHierarchy);
return result;
}
private void collectBeanNamesForType(Set<String> result, ListableBeanFactory beanFactory, Class<?> type,
TypeExtractor typeExtractor, boolean considerHierarchy) {
//先看下 BeanTypeRegistry.get(beanFactory);
BeanTypeRegistry registry = BeanTypeRegistry.get(beanFactory);
//关键这里 registry.getNamesForType(type, typeExtractor)
result.addAll(registry.getNamesForType(type, typeExtractor));
if (considerHierarchy && beanFactory instanceof HierarchicalBeanFactory) {
BeanFactory parent = ((HierarchicalBeanFactory) beanFactory).getParentBeanFactory();
if (parent instanceof ListableBeanFactory) {
collectBeanNamesForType(result, (ListableBeanFactory) parent, type, typeExtractor, considerHierarchy);
}
}
}
注册 BeanTypeRegistry bean定义,并获取实例。
这个就到了熟悉的getBean了,就不用往下看了,回到上面的 collectBeanNamesForType 方法。
继续看 registry.getNamesForType(type, typeExtractor)
可以看到,是与 beanTypes 去匹配查找,那么 beanTypes 的数据从哪里来的?看 updateTypesIfNecessary(); 方法。
先看下 RootBeanDefinition definition = getBeanDefinition(name);
到这里,就再明确不过了,获取的是bean定义,而不是网上那些说的实例。
private void addBeanTypeForNonAliasDefinition(String name) {
//拿到bean定义
RootBeanDefinition definition = getBeanDefinition(name);
if (definition != null) {
//这里就是加到 beanTypes 中去。
addBeanTypeForNonAliasDefinition(name, definition);
}
}
继续看 addBeanTypeForNonAliasDefinition(name, definition); 方法。
private void addBeanTypeForNonAliasDefinition(String name, RootBeanDefinition definition) {
try {
if (!definition.isAbstract() && !requiresEagerInit(definition.getFactoryBeanName())) {
//根据bean定义返回封装的 ResolvableType
ResolvableType factoryMethodReturnType = getFactoryMethodReturnType(definition);
String factoryBeanName = BeanFactory.FACTORY_BEAN_PREFIX + name;
//这里判断是不是 factoryBean,是的话需要特殊处理下。
if (this.beanFactory.isFactoryBean(factoryBeanName)) {
ResolvableType factoryBeanGeneric = getFactoryBeanGeneric(this.beanFactory, definition,
factoryMethodReturnType);
this.beanTypes.put(name, factoryBeanGeneric);
this.beanTypes.put(factoryBeanName, getType(factoryBeanName, factoryMethodReturnType));
}
// 其他的就直接放了。
else {
/*
* getType(name, factoryMethodReturnType) 返回的也是 ResolvableType,
* ResolvableType 是封装了bean定义。
* 这里相当于再去检查一下。
*/
this.beanTypes.put(name, getType(name, factoryMethodReturnType));
}
}
//并且 BeanTypeRegistry 中的还有 beanDefinitions 属性,存放bean定义。
this.beanDefinitions.put(name, definition);
}
catch (CannotLoadBeanClassException ex) {
// Probably contains a placeholder
logIgnoredError("bean class loading failure for bean", name, ex);
}
}
到这里,就把主要的源码分析完了。