AutowiredAnnotationBeanPostProcessor是Spring的後置處理器,專門處理@Autowired和@Value註解。java
postProcessMergedBeanDefinition
方法,查找該Bean是否有@Autowired註解。populateBean
進行屬性注入的時候,即調用postProcessPropertyValues
方法,查找該Bean是否有@Autowired註解。public AutowiredAnnotationBeanPostProcessor() {
//後置處理器將處理@Autowire註解
this.autowiredAnnotationTypes.add(Autowired.class);
//後置處理器將處理@Value註解
this.autowiredAnnotationTypes.add(Value.class);
try {
//後置處理器將處理javax.inject.Inject JSR-330註解
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
複製代碼
//處理類中的屬性,屬性注入
@Override
public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
//獲取指定類中autowire相關注解的元信息
<1> InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//對Bean的屬性進行自動注入
<2> metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
複製代碼
該方法就是在屬性注入populateBean中調用的pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
的具體實現之一。算法
<1> 處的代碼是從該bean中獲取對應的註解信息,在AutowiredAnnotationBeanPostProcessor
這裏就是尋找有加@Value、@Autowired註解的字段,而後把相關信息封裝在InjectionMetadata
。代碼以下:數組
//獲取給定類的autowire相關注解元信息
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
//首先從容器中查找是否有給定類的autowire相關注解元信息
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
//解析給定類autowire相關注解元信息
metadata.clear(pvs);
}
//解析給定類autowire相關注解元信息
metadata = buildAutowiringMetadata(clazz);
//將獲得的給定類autowire相關注解元信息存儲在容器緩存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
複製代碼
下面來看buildAutowiringMetadata
的詳細代碼:緩存
//解析給定類autowire相關注解元信息
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
//建立一個存放註解元信息的集合
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
Class<?> targetClass = clazz;
//遞歸遍歷當前類及其全部基類,解析所有註解元信息
do {
//建立一個存儲當前正在處理類註解元信息的集合
final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();
//利用JDK反射機制獲取給定類中全部的聲明字段,獲取字段上的註解信息
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//獲取給定字段上的註解
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
//若是給定字段是靜態的(static),則直接遍歷下一個字段
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
return;
}
//判斷註解的required屬性值是否有效
boolean required = determineRequiredStatus(ann);
//將當前字段元信息封裝,添加在返回的集合中
currElements.add(new AutowiredFieldElement(field, required));
}
});
//利用JDK反射機制獲取給定類中全部的聲明方法,獲取方法上的註解信息
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
//獲取給定方法上的全部註解
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
//若是方法是靜態的,則直接遍歷下一個方法
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
}
return;
}
//若是方法的參數列表爲空
if (method.getParameterCount() == 0) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
//判斷註解的required屬性值是否有效
boolean required = determineRequiredStatus(ann);
//獲取當前方法的屬性描述符,即方法是可讀的(readable)getter方法,仍是可寫的(writeable)setter方法
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
//將方法元信息封裝添加到返回的元信息集合中
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
//將當前類的註解元信息存放到註解元信息集合中
elements.addAll(0, currElements);
//獲取給定類的父類
targetClass = targetClass.getSuperclass();
}
//若是給定類有基類,而且基類不是Object,則遞歸獲取其基類的元信息
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
複製代碼
這段代碼的註釋很清晰了,到這一步就拿到了指定類中autowire相關注解的元信息。
ps:這裏能夠看到@Autowired註解是不支持static修飾的app
咱們接着看postProcessPropertyValues
方法的<2>處具體的注入邏輯:ide
//InjectionMetadata.java
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
//要注入的字段集合
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
boolean debug = logger.isDebugEnabled();
//遍歷每一個字段 注入
for (InjectedElement element : elementsToIterate) {
if (debug) {
logger.debug("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);
}
}
}
複製代碼
這裏還不是真正注入的方法,咱們繼續追蹤element.inject(target, beanName, pvs);
函數
//InjectionMetadata.java
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable {
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
複製代碼
這是element.inject()
的原始方法,它還有兩個子類本身實現的方法,如圖:post
AutowiredAnnotationBeanPostProcessor
具體的實現。
咱們先來看下對字段的注入:ui
//AutowiredAnnotationBeanPostProcessor.java
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//獲取要注入的字段
Field field = (Field) this.member;
Object value;
//若是字段的值有緩存
if (this.cached) {
//從緩存中獲取字段值value
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
//沒有緩存
else {
//建立一個字段依賴描述符
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
//獲取容器中的類型轉換器
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
//核心!獲取注入的值
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
//線程同步,確保容器中數據一致性
synchronized (this) {
//若是字段的值沒有緩存
if (!this.cached) {
//字段值不爲null,而且required屬性爲true
if (value != null || this.required) {
this.cachedFieldValue = desc;
//爲指定Bean註冊依賴Bean
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
//若是容器中有指定名稱的Bean對象
if (beanFactory.containsBean(autowiredBeanName)) {
//依賴對象類型和字段類型匹配,默認按類型注入
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
//建立一個依賴對象的引用,同時緩存
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
}
//若是獲取的依賴關係爲null,且獲取required屬性爲false
else {
//將字段值的緩存設置爲null
this.cachedFieldValue = null;
}
//容器已經對當前字段的值緩存
this.cached = true;
}
}
}
//若是字段值不爲null
if (value != null) {
//顯式使用JDK的反射機制,設置自動的訪問控制權限爲容許訪問
ReflectionUtils.makeAccessible(field);
//爲字段賦值
field.set(bean, value);
}
}
複製代碼
這段代碼很好理解,從註解@Value/@Autowired中獲取要注入的值,以後利用反射set到字段中。
重點就是怎麼從註解中獲取要注入的值,咱們來看核心代碼value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
this
//DefaultListableBeanFactory.java
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//真正獲取值的代碼
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
複製代碼
進行跟蹤:
//DefaultListableBeanFactory.java
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//注入點
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 針對給定的工廠給定一個快捷實現的方式,例如考慮一些預先解析的信息
// 在進入全部bean的常規類型匹配算法以前,解析算法將首先嚐試經過此方法解析快捷方式。
// 子類能夠覆蓋此方法
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);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
//若是標識@Autowired註解的屬性是複合類型,如Array,Collection,Map,
// 從這個方法獲取@Autowired裏的值
<1> Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//若是標識@Autowired註解的屬性是非複合類型,
// 從這個方法獲取@Autowired裏的值
<2> Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
//若是沒有符合該類型的Bean
if (matchingBeans.isEmpty()) {
// 沒有找到,檢驗 @autowire 的 require 是否爲 true
if (isRequired(descriptor)) {
//拋出異常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
//若是符合該類型的Bean有多個
if (matchingBeans.size() > 1) {
//挑選出最優解
<3> autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
//拋出異常
return descriptor.resolveNotUnique(type, 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();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
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);
}
}
複製代碼
這段代碼看着很長,但其實很容易理解。大體流程就是:
根據字段類型從IOC容器中獲取符合的Bean,若是有多個,則挑選出最優的那一個。
下面來看下具體邏輯。
先來看下@Autowired注入集合數組的邏輯:
//DefaultListableBeanFactory.java
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
Class<?> type = descriptor.getDependencyType();
//若是@Autowired標識的是數組類型的屬性
if (type.isArray()) {
//獲取數組的內容類型
Class<?> componentType = type.getComponentType();
ResolvableType resolvableType = descriptor.getResolvableType();
Class<?> resolvedArrayType = resolvableType.resolve();
if (resolvedArrayType != null && resolvedArrayType != type) {
type = resolvedArrayType;
componentType = resolvableType.getComponentType().resolve();
}
if (componentType == null) {
return null;
}
//經過類型去IOC容器內擇取符合的Bean都是使用這個方法
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
//將獲得的Bean的候選者們轉換爲屬性類型,如從set轉換爲Array,List等
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
if (getDependencyComparator() != null && result instanceof Object[]) {
Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans));
}
return result;
}
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
//獲取Collection的泛型
Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
if (elementType == null) {
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
if (getDependencyComparator() != null && result instanceof List) {
Collections.sort((List<?>) result, adaptDependencyComparator(matchingBeans));
}
return result;
}
else if (Map.class == type) {
ResolvableType mapType = descriptor.getResolvableType().asMap();
Class<?> keyType = mapType.resolveGeneric(0);
if (String.class != keyType) {
return null;
}
Class<?> valueType = mapType.resolveGeneric(1);
if (valueType == null) {
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
return matchingBeans;
}
else {
return null;
}
}
複製代碼
//DefaultListableBeanFactory.java
protected Map<String, Object> findAutowireCandidates( @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
//從IOC容器中獲取全部的符合類型的BeanName,存入候選數組
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
//首先從容器自身註冊的依賴解析來匹配,Spring容器自身註冊了不少Bean的依賴,
//當使用者想要注入指定類型的Bean時,會優先從已註冊的依賴內尋找匹配
for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = this.resolvableDependencies.get(autowiringType);
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
//若是註冊的依賴Bean類型是指定類型的實例或是其父類,接口,則將其做爲候選者,註冊依賴的類型不會重複
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
//遍歷候選數組
for (String candidate : candidateNames) {
//候選Bean不是自引用(即要注入的類不能是類自己,會觸發無限遞歸注入)
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !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)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
// 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;
}
複製代碼
這段代碼註釋已經寫的很清楚了,咱們來繼續看下addCandidateEntry
方法,該方法是把Bean實例放入到候選者集合中
//DefaultListableBeanFactory.java
private void addCandidateEntry(Map<String, Object> candidates, String candidateName, DependencyDescriptor descriptor, Class<?> requiredType) {
//當@Autowired標識的是容器類型的屬性,生成的依賴描述類型是MultiElementDescriptor ,
//所以全部的候選者均是合格的,因此會當場實例化他們。而若是屬性的類型非容器,那麼多是多個候選者中挑一個,
//此時實例化他們全部就不合適了,最終會把合格的那個實例化,若是沒有合格的則不實例化,
//提早實例化對Bean的不少方面有影響,好比AOP,EarlyReference等 */
if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) {
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
}
else {
candidates.put(candidateName, getType(candidateName));
}
}
複製代碼
這裏會調用doGetBean()方法進行實例化Bean
若是根據類型從IOC容器中得到的Bean有多個,那麼就須要調用determineAutowireCandidate(matchingBeans, descriptor)
方法,去挑選出最優解。
代碼:
//DefaultListableBeanFactory.java
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
//根據@Primary註解來擇取最優解
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
//根據@Order,@PriorityOrder,及實現Order接口的序號來擇取最優解
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
//若是經過以上兩步都不能選擇出最優解,則使用最基本的策略
//首先若是這個類型已經由Spring註冊過依賴關係對,則直接使用註冊的對象,
//候選者集合是LinkedHashMap,有序Map集合,容器註冊的依賴對象位於LinkedHashMap的起始位置
//若是沒有註冊過此類型的依賴關係,則根據屬性的名稱來匹配,、
//若是屬性名稱和某個候選者的Bean名稱或別名一致,那麼直接將此Bean做爲最優解
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
複製代碼
這部分邏輯比較簡單,總結就是3個步驟:
咱們逐一分析這幾個步驟,先看第一個:
根據@Primary註解來擇取最優解
//DefaultListableBeanFactory.java
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();
//候選者能夠是父容器內的標識了@Primary的Bean,也能夠是當前容器的。SpringMVC容器將Spring容器做爲父容器
if (isPrimary(candidateBeanName, beanInstance)) {
if (primaryBeanName != null) {
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
//此處確保同一個容器中同一個類型的多個Bean最多隻有一個Bean標識了@Primary
if (candidateLocal && primaryLocal) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());
}
//若是上一個@Primary的Bean是父容器的,則用當前容器的候選者覆蓋以前的@Primary的Bean
else if (candidateLocal) {
primaryBeanName = candidateBeanName;
}
}
else {
primaryBeanName = candidateBeanName;
}
}
}
return primaryBeanName;
}
複製代碼
接着看第二個:
根據@Order,@PriorityOrder
//DefaultListableBeanFactory.java
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String highestPriorityBeanName = null;
Integer highestPriority = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
Integer candidatePriority = getPriority(beanInstance);
if (candidatePriority != null) {
//不能同時存在兩個最高優先級的序號
if (highestPriorityBeanName != null) {
if (candidatePriority.equals(highestPriority)) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same priority ('" + highestPriority +
"') among candidates: " + candidates.keySet());
}
//使用優先級序號最小的Bean做爲最優解
else if (candidatePriority < highestPriority) {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
else {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
}
return highestPriorityBeanName;
}
複製代碼
小結:
到這裏,@Autowired字段注入的源碼就分析完畢了。
接下來咱們看下方法注入:
//DefaultListableBeanFactory.java
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//若是屬性被顯式設置爲skip,則不進行注入
if (checkPropertySkipping(pvs)) {
return;
}
//獲取注入元素對象
Method method = (Method) this.member;
Object[] arguments;
//若是容器對當前方法緩存
if (this.cached) {
// Shortcut for avoiding synchronization...
//獲取緩存中指定Bean名稱的方法參數
arguments = resolveCachedArguments(beanName);
}
//若是沒有緩存
else {
//獲取方法的參數列表
Class<?>[] paramTypes = method.getParameterTypes();
//建立一個存放方法參數的數組
arguments = new Object[paramTypes.length];
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length);
Assert.state(beanFactory != null, "No BeanFactory available");
//獲取容器的類型轉換器
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < arguments.length; i++) {
//建立方法參數對象
MethodParameter methodParam = new MethodParameter(method, i);
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
currDesc.setContainingClass(bean.getClass());
//解析方法的輸入參數,爲方法參數建立依賴描述符
descriptors[i] = currDesc;
try {
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
//根據容器中Bean定義解析依賴關係,獲取方法參數依賴對象
arguments[i] = arg;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
}
}
//線程同步,以確保容器中數據一致性
synchronized (this) {
//若是當前方法沒有被容器緩存
if (!this.cached) {
//若是方法的參數列表不爲空
if (arguments != null) {
//爲容器中緩存方法參數的對象賦值
Object[] cachedMethodArguments = new Object[paramTypes.length];
for (int i = 0; i < arguments.length; i++) {
cachedMethodArguments[i] = descriptors[i];
}
//爲指定Bean註冊依賴Bean
registerDependentBeans(beanName, autowiredBeans);
//若是依賴對象集合大小等於方法參數個數
if (autowiredBeans.size() == paramTypes.length) {
Iterator<String> it = autowiredBeans.iterator();
//爲方法參數設置依賴對象
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
//若是容器中存在指定名稱的Bean對象
if (beanFactory.containsBean(autowiredBeanName)) {
//若是參數類型和依賴對象類型匹配
if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
//建立一個依賴對象的引用,複製給方法相應的參
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
}
//若是方法參數列表爲null,則設置容器對該方法參數的緩存爲null
else {
this.cachedMethodArguments = null;
}
//設置容器已經對該方法緩存
this.cached = true;
}
}
}
//若是方法參數依賴對象不爲null
if (arguments != null) {
try {
//使用JDK的反射機制,顯式設置方法的訪問控制權限爲容許訪問
ReflectionUtils.makeAccessible(method);
//調用Bean的指定方法
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex){
throw ex.getTargetException();
}
}
}
複製代碼
總結
@Autowired註解的原理用一句話講明: 就是先從IOC容器中根據類型找到全部符合的Bean,而後再根據@Primary、@Order、@PriorityOrder或Spring默認規則挑選出最符合的Bean,利用反射注入到字段中。