在SpringBoot中有许多类使用到了@Primary注解,关于用法,请看这篇博客:在spring中常被忽视的注解 @Primary。
这次我们不说用法,从源码层面来看下:
一、入口
在创建bean的时候,我们会获取bean的依赖bean,这个方法就是DefaultListableBeanFactory的doResolveDependency方法,如果匹配的bean大于1,会执行如下方法:
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
二、查找
最后会进入DefaultListableBeanFactory的如下方法,进行bean的过滤
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String primaryBeanName = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (isPrimary(candidateBeanName, beanInstance)) {
if (primaryBeanName != null) {
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
if (candidateLocal && primaryLocal) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());
}
else if (candidateLocal) {
primaryBeanName = candidateBeanName;
}
}
else {
primaryBeanName = candidateBeanName;
}
}
}
return primaryBeanName;
}
isPrimary方法是判断是否有@Primary注解,如果有多个满足条件的bean有@Primary注解就会抛出异常:
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());