閱讀此需閱讀下面這些博客先 |
---|
【Spring源碼分析】Bean的元數(shù)據(jù)和一些Spring的工具 |
【Spring源碼分析】BeanFactory系列接口解讀 |
【Spring源碼分析】執(zhí)行流程之非懶加載單例Bean的實(shí)例化邏輯 |
【Spring源碼分析】從源碼角度去熟悉依賴注入(一) |
上篇這里簡單提一下哈,怕有些沒看的,這是連著的…:
- 上篇是提了下生命周期的屬性注入階段,也就是 populateBean 的具體實(shí)現(xiàn);
- 然后里面涉及到實(shí)例化后階段,和三種注入方式,Spring的BYNAME和BYTYPE還有通過MergedBeanDefinitionPostProcessor 去重定義 BeanDefinition 時(shí)的注入這倆種是簡單提了一下,然后就準(zhǔn)備去詳細(xì)分析一下使用@Autowired注解是如何注入的呢?這就涉及到 InstantiationAwareBeanPostProcessor 的實(shí)現(xiàn)類 AutowiredAnnotationBeanPostProcessor 里的具體實(shí)現(xiàn)了;
- 然后就去簡單分析了一下是注入的,首先是去遍歷屬性和方法,看誰有 @Autowired、@Value 這倆注解,有就創(chuàng)建對(duì)應(yīng)的 InjectElement 然后進(jìn)行注入。
這篇呢主要就是去分析一下 AutowiredFieldElement 和 AutowiredMethodElement 里注入的具體實(shí)現(xiàn)。
也是對(duì)應(yīng)著下面流程圖中的 如何去尋找Bean的?
一、AutowiredFieldElement 注入分析
注入屬性,就是去找到對(duì)應(yīng)Bean,然后通過反射去賦值了,所以咱具體看看 resolveFieldValue(這上篇都有說過):往里看,可以注意到其解析依賴獲取Bean的邏輯是通過 beanFactory#resolveDependency 去實(shí)現(xiàn)的,傳的參數(shù)有倆主要的就是類型轉(zhuǎn)化器和屬性描述對(duì)象(它是 AutowiredCapableBeanFactory 接口里的一個(gè)方法,即使不說,也應(yīng)該猜到,畢竟這是在屬性注入流程里出現(xiàn)的):
上篇說了,AutowiredAnnotationBeanPostProcessor 是有實(shí)現(xiàn) BeanFactoryAware 接口的,那么它在初始化前就會(huì)去操作把 BeanFactory 注入到它這里面,注入的是
DefaultListableBeanFactory
,然后它向上轉(zhuǎn)型成了 ConfigurableListableBeanFactory
,轉(zhuǎn)不轉(zhuǎn)都一樣,ConfigurableListableBeanFactory 接口本就覆蓋了所有 BeanFactory 接口系列的功能,這前面也闡述過:
那也就是說,咱接下來得分析,DefaultListableBeanFactory#resolveDependency
,在分析之前得清除,這是 DefaultListableBeanFactory 下的方法實(shí)現(xiàn),而傳的參數(shù) DependencyDescriptor 也是注入點(diǎn)的子類,就是說其可以描述構(gòu)造參數(shù)、屬性、方法參數(shù),即該方法不管是注入的公共方法,包括屬性和方法(所以如果碰到關(guān)系方法的地方不要懵,比如下面的第一行)。
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 用來獲取方法入?yún)⒚值?/span>
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 所需要的類型是Optional
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
// 所需要的的類型是ObjectFactory,或ObjectProvider
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
// 在屬性或set方法上使用了@Lazy注解,那么則構(gòu)造一個(gè)代理對(duì)象并返回,真正使用該代理對(duì)象時(shí)才進(jìn)行類型篩選Bean
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// descriptor表示某個(gè)屬性或某個(gè)set方法
// requestingBeanName表示正在進(jìn)行依賴注入的Bean
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
- 首先是獲取到參數(shù)的名字,這肯定是字節(jié)碼層面的,咱別去細(xì)究了;
- 然后是去對(duì)類型進(jìn)行判斷,Optional、ObjectFactory、ObjectProvider、javax下的那Provider,這些俺幾乎不用,不去詳細(xì)看了,直接看else的邏輯;
- 判斷參數(shù)上是不是加了
@Lazy
注解,如果加了表示該Bean注入進(jìn)行懶加載,這樣就話返回的就是一個(gè)CGLIB
的動(dòng)態(tài)代理對(duì)象。- 在 Mybatis 源碼分析里,咱遇到過Javassit、jdk、CGLIB 三種動(dòng)態(tài)代理,這里為什么選擇 CGLIB原因如下:它不是運(yùn)行時(shí)候用的,它是直接Spring加載的時(shí)候進(jìn)行的,所以不需要Javassit 去做,而jdk動(dòng)態(tài)代理是在接口層面的,屬性注入肯定不僅僅是類,所以毫無疑問 CGLIB 是這里最好的選擇了。
- 如果沒用 @Lazy 的話,就是正常構(gòu)造了,調(diào)用
doResolveDependency
方法。
下面有做懶加載的測試:可以看見這調(diào)試的是一個(gè)代理對(duì)象,且是 CGLIB 代理:
doResolveDependency 方法是解決屬性注入的核心,咱分標(biāo)題去分析。下面看一下,AutowiredMethodElement的注入,將倆關(guān)聯(lián)起來。
二、AutowiredMethodElement注入分析
有關(guān)方法方式的注入,主要是在 resolveMethodArguments 方法中進(jìn)行:
里面的實(shí)現(xiàn)邏輯就是去遍歷每一個(gè)參數(shù),然后去調(diào)用
DefaultListableBeanFactory#resolveDependency
方法獲取到對(duì)應(yīng)的Bean,然后放到數(shù)組中,最后返回。
至于 resolveDependency 的實(shí)現(xiàn)邏輯,就和上面串起來了。
三、doResolveDependency 源碼分析
(吐槽一下,本來就是這部分注入流程都在這里,我分析源碼解讀算細(xì)了,但CSDN md 惡心人,昨天寫的今天打開草稿一看全沒了,我是真服了)
先給出源碼,再針對(duì)源碼各部分依次解讀:
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 如果當(dāng)前descriptor之前做過依賴注入了,則可以直接取shortcut了,相當(dāng)于緩存
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
// 獲取@Value所指定的值
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
// 占位符填充(${})
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
// 解析Spring表達(dá)式(#{})
value = evaluateBeanDefinitionString(strVal, bd);
}
// 將value轉(zhuǎn)化為descriptor所對(duì)應(yīng)的類型
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// 如果descriptor所對(duì)應(yīng)的類型是數(shù)組、Map這些,就將descriptor對(duì)應(yīng)的類型所匹配的所有bean方法,不用進(jìn)一步做篩選了
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 找到所有Bean,key是beanName, value有可能是bean對(duì)象,有可能是beanClass
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// required為true,拋異常
// 找不到對(duì)應(yīng)的Bean,但是 required 又是 true,就會(huì)拋出異常,@Autowired 的 required 默認(rèn)是 true 的
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
// 根據(jù)類型找到了多個(gè)Bean,進(jìn)一步篩選出某一個(gè), @Primary-->優(yōu)先級(jí)最高--->name
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
// 記錄匹配過的beanName
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
// 有可能篩選出來的是某個(gè)bean的類型,此處就進(jìn)行實(shí)例化,調(diào)用getBean
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
1. @Value 注解解析
在判定字段和方法是否為注入點(diǎn)時(shí),除了判定 @Autowired 注解還有就是 @Value 注解。而這里就是對(duì) @Value 注解進(jìn)行解析:
Class<?> type = descriptor.getDependencyType();
// 獲取@Value所指定的值
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
// 占位符填充(${})
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
// 解析Spring表達(dá)式(#{})
value = evaluateBeanDefinitionString(strVal, bd);
}
// 將value轉(zhuǎn)化為descriptor所對(duì)應(yīng)的類型
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
解析過程很簡單,就是拿到 @Value
注解中的內(nèi)容,若是 ${}
開頭就去 Environment
中去尋其結(jié)果。要是 #{}
開頭就是用 SPEL
表達(dá)式解析器去解析。
不管是從環(huán)境對(duì)象(配置文件、系統(tǒng)配置、總環(huán)境配置)中去找還是SPEL表達(dá)式解析,最后都有一個(gè)值,然后再交給轉(zhuǎn)換器進(jìn)行轉(zhuǎn)換得到結(jié)果后返回。
測試 ${} 和 #{}
編寫對(duì)應(yīng)配置:引入配置:
測試:
2. resolveMultipleBeans 篩選特殊類型(處理多Bean)
// 如果descriptor所對(duì)應(yīng)的類型是數(shù)組、Map這些,就將descriptor對(duì)應(yīng)的類型所匹配的所有bean方法,不用進(jìn)一步做篩選了
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
resolveMultipleBeans
方法對(duì) Stream、數(shù)組、Collection、Map
這三種情況進(jìn)行了處理。
其實(shí)處理方式大致都一樣,這里隨便抽一種類型進(jìn)行解釋,其他的你們能懂。
Map 的處理方式如下:
- 主要就是去找到 Map 上對(duì)應(yīng)的泛型類型;
- 然后通過Value泛型的類型去調(diào)用 findAutowireCandidates 方法去根據(jù)類型找對(duì)應(yīng)的Beans,返回的是一個(gè) Map<String,Object> 其中key 是 beanName,Value 是對(duì)應(yīng)的Bean。
- 若是其他類型的話就這個(gè)Map進(jìn)行些處理,然后返回結(jié)果集就好了,這 Map 是不需要處理的,然后就直接返回了。
測試
findAutowireCandidates 方法解析
這個(gè)方法很重要,也很難,主要概括下就是通過類型去找對(duì)應(yīng)Bean的Map集合,Key 是 BeanName,Value 的話是對(duì)應(yīng)的Bean或者是對(duì)應(yīng)的Class對(duì)象。
先給出源碼的解析:
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
// 從BeanFactory中找出和requiredType所匹配的beanName,僅僅是beanName,這些bean不一定經(jīng)過了實(shí)例化,只有到最終確定某個(gè)Bean了,如果這個(gè)Bean還沒有實(shí)例化才會(huì)真正進(jìn)行實(shí)例化
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
// 根據(jù)類型從resolvableDependencies中匹配Bean,resolvableDependencies中存放的是類型:Bean對(duì)象,比如BeanFactory.class:BeanFactory對(duì)象,在Spring啟動(dòng)時(shí)設(shè)置
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
for (String candidate : candidateNames) {
// 如果不是自己,則判斷該candidate到底能不能用來進(jìn)行自動(dòng)注入
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 為空要么是真的沒有匹配的,要么是匹配的自己
if (result.isEmpty()) {
// 需要匹配的類型是不是Map、數(shù)組之類的
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 匹配的是自己,被自己添加到result中
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
咱先對(duì)整體的流程進(jìn)行個(gè)概述:
-
BeanFactoryUtils.beanNamesForTypeIncludingAncestors
是去根據(jù)類型去找到對(duì)應(yīng)的 beanNames,這個(gè)是真正的根據(jù)類型去找。內(nèi)部實(shí)現(xiàn)概述起來不難,就是去遍歷所有的beanNames,如果單例池中有就拿bean出來,沒有就去找對(duì)應(yīng)的beanDefinition,那里面在掃描過程中有把Class實(shí)體存進(jìn)去,那么直接instanceOf
就知道合不合要求了。 -
下一步就是去遍歷Spring啟動(dòng)的時(shí)候會(huì)放入寫實(shí)體放到
resolvableDependencies
下,就是這些類型的話也是可以被注入的,我所說的有如下幾個(gè):- beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
- beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
-
對(duì)注入的不是自己再度進(jìn)行篩選,通過的
isAutowireCandidate
方法,這里用了責(zé)任鏈的設(shè)計(jì)模式,下面會(huì)再度概述這點(diǎn)。 -
如果篩選到最后沒一個(gè)符合的,就會(huì)去判斷是否引用的自己,是的話放入返回的結(jié)果集中。
isAutowireCandidate 源碼分析
這個(gè)是 findAutowireCandidates 中的第三點(diǎn),前倆點(diǎn)主要是找可以注入的實(shí)體,只有第三點(diǎn)是會(huì)進(jìn)行再次篩選。
isAutowireCandidate 這個(gè)方法是一個(gè)重載方法,只有它返回為true,才會(huì)嘗試放入返回結(jié)果集中,我們直接看最核心的這個(gè)方法。看來看去最后是以
AutowireCandidateResolver#isAutowireCandidate
為返回結(jié)果:
在分析之前,還是得看一下這個(gè)關(guān)系圖;源碼中所使用的 AutowireCandidatesResolver 實(shí)體就是
QualifierAnnotationAutowireCandidateResolver
實(shí)體對(duì)象,接下來咱就看看它的 #isAutowireCandidate 的實(shí)現(xiàn):它首先是去父類的篩選,若父類篩選不通過的話就直接返回FALSE了,不會(huì)執(zhí)行if里的代碼。
而 if 里面的代碼就是對(duì) @Qualifier
注解(限定符)的篩選,若原實(shí)體和注入字段上有@Qualifier注解就去比對(duì)里面的Value值。
父類 GenericTypeAwareAutowireCandidateResolver 解析也是一樣,先交給父類,然后再嘗試自己執(zhí)行,這個(gè)是去解析泛型的,一點(diǎn)復(fù)雜,不解析了。
再往上的話就是 SimpleAutowireCandidateResolver 去解析了,就是判斷BeanDefinition中的autowireCandidate是不是為true,默認(rèn)是true的,允許注入:
這是典型的責(zé)任鏈設(shè)計(jì)模式,其中執(zhí)行流程是 SimpleAutowireCandidateResolver -》GenericTypeAwareAutowireCandidateResolver -》QualifierAnnotationAutowireCandidateResolver,沒前一步都影響后續(xù)的執(zhí)行,相比過濾器那種它只是沒有前置處理,也不需要。
測試
對(duì)上面的三種過濾形式進(jìn)行個(gè)簡單測試好理解:
SimpleAutowireCandidateResolver 主要是去判斷 autowireCandidate 是不是為true。
下面我把 autowireCandidate 設(shè)置為了 FALSE,那么注入肯定會(huì)報(bào)錯(cuò)的(報(bào)錯(cuò)位置應(yīng)該是在 doResolveDependency 中找不到對(duì)應(yīng)注入實(shí)體,但是 required 又是true):然后就是 GenericTypeAwareAutowireCandidateResolver 解析器去對(duì)泛型的篩選,如下所示:
public class BaseService<O, S> {
@Autowired
protected O o;
@Autowired
protected S s;
}
BaseService 中定義了泛型,然后 UserService 繼承了 BaseService 然后指定了泛型類型,這里就是對(duì)這個(gè)泛型類型進(jìn)行篩選。由于這里是泛型,在起初 BeanFactoryUtils.beanNamesForTypeIncludingAncestors 得到的結(jié)果是所有的 beanNames,而這里就可以得到泛型類型的真正篩選。
打斷點(diǎn)測試:可以發(fā)現(xiàn)要注入的類型是 Object,而篩選出來的結(jié)果是所有的 beanName
而那流程執(zhí)行結(jié)束看結(jié)果:
最后輸出:而
QualifierAnnotationAutowireCandidateResolver
去解析@Qualifier我覺得開發(fā)過的對(duì)這個(gè)應(yīng)該都不陌生的。
無非就是去標(biāo)志一下,最后注入的時(shí)候需要比對(duì)一下:
比如下面提供幾種負(fù)載均衡策略實(shí)體,然后通過注解自由注入例子:
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("random")
public @interface Random {
}
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("roundRobin")
public @interface RoundRobin {
}
public interface LoadBalance {
String select();
}
@Component
@Random
public class RandomStrategy implements LoadBalance {
@Override
public String select() {
return null;
}
}
@Component
@RoundRobin
public class RoundRobinStrategy implements LoadBalance {
@Override
public String select() {
return null;
}
}
無非就是前后限定符的比對(duì)。
3. 根據(jù)類型找Bean沒找著且required=true
// 找到所有Bean,key是beanName, value有可能是bean對(duì)象,有可能是beanClass
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// required為true,拋異常
// 找不到對(duì)應(yīng)的Bean,但是 required 又是 true,就會(huì)拋出異常,@Autowired 的 required 默認(rèn)是 true 的
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
通過 findAutowireCandidates 要是沒有找到結(jié)果集的話,就說明沒有匹配的 Bean,那么這時(shí)required又是true,默認(rèn)就是true,那么這時(shí)會(huì)拋出異常。
4. 尋找唯一Bean(普通注入)
現(xiàn)在就是我們最常見的注入了,就是普通的注入,前面奇奇怪怪的都被篩選光了。
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
// 根據(jù)類型找到了多個(gè)Bean,進(jìn)一步篩選出某一個(gè), @Primary-->優(yōu)先級(jí)最高--->name
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
這里的話會(huì)先進(jìn)行判斷,若 findAutowireCandidates 返回的結(jié)果集是多個(gè)那就進(jìn)行再處理,若是一個(gè)則沒啥好說的,直接返回到時(shí)候反射賦值就是了。那咱就看看它多個(gè)的情況下又會(huì)做哪些處理吧,主要是在 determineAutowireCandidate
方法中。
這個(gè)方法實(shí)現(xiàn)不難,主要就是三層篩選,先@Primary,再@Priority,前倆者都沒的話就根據(jù)名字了。
@Nullable
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
// candidates表示根據(jù)類型所找到的多個(gè)Bean,判斷這些Bean中是否有一個(gè)是@Primary的
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
// 取優(yōu)先級(jí)最高的Bean
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
// 匹配descriptor的名字,要么是字段的名字,要么是set方法入?yún)⒌拿?/span>
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
// resolvableDependencies記錄了某個(gè)類型對(duì)應(yīng)某個(gè)Bean,啟動(dòng)Spring時(shí)會(huì)進(jìn)行設(shè)置,比如BeanFactory.class對(duì)應(yīng)BeanFactory實(shí)例
// 注意:如果是Spring自己的byType,descriptor.getDependencyName()將返回空,只有是@Autowired才會(huì)方法屬性名或方法參數(shù)名
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
@Priority 注解的篩選要看一下,是以值越小優(yōu)先級(jí)越高來判斷的:
其它就沒啥好說的。
四、總結(jié)
這簡單做個(gè)小結(jié)吧,注意這里是和上一節(jié)是一起的:
- 這個(gè)屬性注入呢考慮的是去遍歷 InstantiationAwareBeanPostProcessor 中的屬性注入方法調(diào)用,其中有個(gè)
AutowiredAnnotationBeanPostProcessor
就是我們所分析的。 - 首先呢就是去遍歷屬性遍歷方法尋找注入點(diǎn),找到后封裝成一個(gè)注入點(diǎn)實(shí)體存進(jìn)集合中;
- 遍歷這個(gè)集合依次進(jìn)行注入,要是方法的話就參數(shù)遍歷個(gè)遍去調(diào)用
doResolverDependency
方法獲取要注入的bean,最后合一起反射調(diào)用方法就是了,屬性的話,更簡單,獲取后反射直接賦值。 - doResolveDependency邏輯:
- 先進(jìn)行
@Value
注解的注入; - 篩選
Map、Stream、Collection、數(shù)組
這特殊類型; - findAutowireCandidates 去根據(jù)類型篩選Bean,其中篩選有 autowireCandidate 需要為 true,篩選泛型類型,篩選 @Qualifier 限定符匹配的。
- 若有多Bean需要注入還需要進(jìn)行篩選:
@Primary
-
@Priority
(注意這里是值越小優(yōu)先級(jí)越高,且值不能一樣,不然拋異常的) - 屬性名或者說是參數(shù)名和 beanName 匹配一個(gè)出來。
- 先進(jìn)行
- 反射調(diào)用/反射賦值(完成依賴注入!?。。?/li>
篩選6步記住:@Value ---- autowireCandidate 元數(shù)據(jù)屬性要為 true ----- @Qualifier 限定符若有需匹配 ------- 多Bean的話 @Primary --------@Priority ------屬性名或者參數(shù)名匹配
下一篇的話把 @Resource 注解注入源碼也分析一下,其實(shí)可以猜到,也得通過 InstantiationAwareBeanPostProcessor 中的屬性注入方法的遍歷。文章來源:http://www.zghlxwxcb.cn/news/detail-824369.html
搞個(gè)流程圖就像如下步驟一樣:文章來源地址http://www.zghlxwxcb.cn/news/detail-824369.html
到了這里,關(guān)于【Spring源碼分析】從源碼角度去熟悉依賴注入(二)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!