這是我學習Spring源碼以後的第四篇文章,若是你想了解,以前的3篇文章請您查閱:java
前3篇blog的地址:
1.Spring源碼學習(-)別怕,老外點中餐與AbstractBeanFactory.getBean的主流程差很少
2.Spring源碼學習(二)哎呦,按菜譜作菜與AbstractAutowireCapableBeanFactory.createBean流程差很少
3.pring源碼學習(三)炒雞丁與populateBean沒區別)bash
我常常寫以下代碼:學習
@Autowired private AService aservice;
複製代碼
不知你是否也好奇,Spring是若是找到AService類型的Bean的呢?,此文,咱們就聊聊這個->單值注入時如何按類型查找匹配的Bean.ui
很簡單,核心就3步。this
Spring在DefaultListableBeanFactory.findAutowireCandidates方法中實現。 其部分源碼以下:spa
String[] candidateNames =
BeanFactoryUtils .beanNamesForTypeIncludingAncestors
( this, requiredType, true, descriptor.isEager());
複製代碼
這個beanNamesForTypeIncludingAncestors的做用就是,獲取requiredType(AService)類型全部匹配的beanName(包含先祖BeanFactory)。.net
beanNamesForTypeIncludingAncestors內部是若是實現的呢?我歸納了下簡要邏輯以下:code
遍歷全部的BeanDefinition,得到全部的BeanName.cdn
針對全部的BeanName,先嚐試獲取單例進行匹配,若未匹配上再以Bean Definition進行匹配。blog
匹配時,若是Bean是FactoryBean,先嚐試FactoryBean生產的實際Bean進行匹配,若未匹配上再以FactoryBean 進行匹配。
DefaultListableBeanFactory.determinePrimaryCandidate實現了篩選首選Bean的邏輯, 其中的核心方法是isPrimary,該方法是判斷當前Bean是不是首選Bean的。源碼以下:
protected boolean isPrimary(String beanName, Object beanInstance) {
if (containsBeanDefinition(beanName)) {
return getMergedLocalBeanDefinition(beanName).isPrimary();
}
BeanFactory parent = getParentBeanFactory();
return (parent instanceof DefaultListableBeanFactory && ((DefaultListableBeanFactory) parent).isPrimary(beanName,beanInstance));
}
複製代碼
getMergedLocalBeanDefinition(beanName).isPrimary()方法,對應AbstractBeanDefinition的primary屬性,該屬性被賦值的地方是在AnnotatedBeanDefinitionReader.doRegisterBean方法中。有以下邏輯。
//省略甚多代碼......
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
//省略不少代碼....
複製代碼
看到這,咱們能夠得出一個結論:
被@Primary註解的bean,單值注入時會做爲首選。
Spring是如何肯定Bean的優先級的呢?
在DefaultListableBeanFactory.determineHighestPriorityCandidate中,實現按優先級選擇Bean 其中,獲取Bean的優先級的邏輯在getPriority方法中,以下:
protected Integer getPriority(Object beanInstance) {
Comparator<Object> comparator = getDependencyComparator();
if (comparator instanceof OrderComparator) {
return ((OrderComparator) comparator).getPriority(beanInstance);
}
return null;
}
複製代碼
查看OrderComparator的實現類AnnotationAwareOrderComparator中的源碼發現, 獲取優先級的邏輯實際在在OrderUtils.getPriority 中
public static Integer getPriority(Class<?> type) {
if (priorityAnnotationType == null) {
return null;
}
Object cached = priorityCache.get(type);
if (cached != null) {
return (cached instanceof Integer ? (Integer) cached : null);
}
Annotation priority = AnnotationUtils.findAnnotation(type, priorityAnnotationType);
Integer result = null;
if (priority != null) {
result = (Integer) AnnotationUtils.getValue(priority);
}
priorityCache.put(type, (result != null ? result : NOT_ANNOTATED));
return result;
}
複製代碼
在OrderUtils 向上查找發現 priorityAnnotationType的值爲:
priorityAnnotationType = (Class<? extends Annotation>) ClassUtils.forName("javax.annotation.Priority", OrderUtils.class.getClassLoader());
複製代碼
被@Priority註解的類,其值越小,在單值注入時,越優先選擇。
Spring的源碼很是多,僅有這3步固然是不行的,我準備了流程圖,梳理了Spring單值注入時查找匹配Bean的流程。
更加細緻的部分,仍是要本身看代碼哦。
下一篇想嘗試寫後處理,預計最晚10月13日!!,祝你們節日快樂!