1. 程式人生 > 程式設計 >你所不知道的Spring的@Autowired實現細節分析

你所不知道的Spring的@Autowired實現細節分析

前言

相信很多Java開發都遇到過一個面試題:Resource和Autowired的區別是什麼?這個問題的答案相信基本都清楚,但是這兩者在Spring中是如何實現的呢?這就要分析Spring原始碼才能知道了。友情提示:本篇主要是講解Autowired的實現原理,不會分析Spring初始化的過程,不熟悉的讀者可以先閱讀筆者之前的一篇文章《這一次搞懂Spring的Bean例項化原理》。

正文

在Spring Bean的整個建立過程中會呼叫很多BeanPostProcessor介面的的實現類:

你所不知道的Spring的@Autowired實現細節分析

上圖是我整理的Spring Bean的建立過程及整個過程中各個BeanPostProcessor和回撥的呼叫,右邊相同顏色的連線代表是同一組呼叫,主要看到AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor,前者就是支援 @Autowired和@Value註解,後者則是支援@PostConstruct、@PreDestroy、@Resource註解。先了解這兩個Processor的作用,下面從頭分析。

從圖中可以看到,在createBeanInstance方法中會呼叫SmartInstantiationAwareBeanPostProcessor型別的determineCandidateConstructors,這個方法是做什麼的呢?看程式碼:

protected BeanWrapper createBeanInstance(String beanName,RootBeanDefinition mbd,@Nullable Object[] args) {
 ......
 // Candidate constructors for autowiring?
 //尋找當前正在例項化的bean中有@Autowired註解的建構函式
 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass,beanName);
 if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
 //如果ctors不為空,就說明建構函式上有@Autowired註解
 return autowireConstructor(beanName,mbd,ctors,args);
 } 
 ......
 
 // No special handling: simply use no-arg constructor.
 return instantiateBean(beanName,mbd);
 }

 protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass,String beanName)
 throws BeansException {

 if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
 for (BeanPostProcessor bp : getBeanPostProcessors()) {
 if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
  SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
  Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass,beanName);
  if (ctors != null) {
  return ctors;
  }
 }
 }
 }
 return null;
 }

createBeanInstance方法是去例項化Bean,而呼叫AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors的目的就是先去找到帶有@Autowired註解的構造方法(自動注入有三種模式:屬性、構造方法、普通方法),也就是通過構造方法注入,如果沒有找到則通過反射呼叫無參構造例項化。平時我們基本上都是使用的屬性注入,所以一般都不會進入determineCandidateConstructors方法,所以這裡也不詳細闡述,感興趣的讀者可自行看看。

接著回到doCreateBean方法中,就可以看到呼叫了applyMergedBeanDefinitionPostProcessors方法:

 protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd,Class<?> beanType,String beanName) {
 for (BeanPostProcessor bp : getBeanPostProcessors()) {
 if (bp instanceof MergedBeanDefinitionPostProcessor) {
 /**
  * CommonAnnotationBeanPostProcessor 支援了@PostConstruct,@PreDestroy,@Resource註解
  * AutowiredAnnotationBeanPostProcessor 支援 @Autowired,@Value註解
  */
 MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
 bdp.postProcessMergedBeanDefinition(mbd,beanType,beanName);
 }
 }
 }

這個方法本質上就是呼叫MergedBeanDefinitionPostProcessor型別的postProcessMergedBeanDefinition方法,通過這個方法去收集@Autowired、@Resource等註解,這裡主要分析AutowiredAnnotationBeanPostProcessor的實現:

 public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,String beanName) {
 InjectionMetadata metadata = findAutowiringMetadata(beanName,null);
 metadata.checkConfigMembers(beanDefinition);
 }

 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.
 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) {
  metadata.clear(pvs);
  }
  //主要看這個方法
  metadata = buildAutowiringMetadata(clazz);
  this.injectionMetadataCache.put(cacheKey,metadata);
 }
 }
 }
 return metadata;
 }

 private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
 List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
 Class<?> targetClass = clazz;

 do {
 final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

 // 找到帶有@Autowired註解的屬性並封裝為AnnotationAttributes
 ReflectionUtils.doWithLocalFields(targetClass,field -> {
 AnnotationAttributes ann = findAutowiredAnnotation(field);
 if (ann != null) {
  if (Modifier.isStatic(field.getModifiers())) {
  if (logger.isInfoEnabled()) {
  logger.info("Autowired annotation is not supported on static fields: " + field);
  }
  return;
  }
  boolean required = determineRequiredStatus(ann);
  currElements.add(new AutowiredFieldElement(field,required));
 }
 });

 // 找到帶有@Autowired註解的方法並封裝為AnnotationAttributes
 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.isInfoEnabled()) {
  logger.info("Autowired annotation is not supported on static methods: " + method);
  }
  return;
  }
  if (method.getParameterCount() == 0) {
  if (logger.isInfoEnabled()) {
  logger.info("Autowired annotation should only be used on methods with parameters: " +
   method);
  }
  }
  boolean required = determineRequiredStatus(ann);
  PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod,clazz);
  currElements.add(new AutowiredMethodElement(method,required,pd));
 }
 });

 elements.addAll(0,currElements);
 targetClass = targetClass.getSuperclass();
 }
 while (targetClass != null && targetClass != Object.class);

 return new InjectionMetadata(clazz,elements);
 }

收集的邏輯主要在findAutowiringMetadata方法中,層層呼叫後可以看到是通過findAutowiredAnnotation這個方法去找到帶有@Autowired和@Value註解的屬性和方法:

 private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);

 public AutowiredAnnotationBeanPostProcessor() {
 this.autowiredAnnotationTypes.add(Autowired.class);
 this.autowiredAnnotationTypes.add(Value.class);
 try {
 this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
  ClassUtils.forName("javax.inject.Inject",AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
 logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
 }
 catch (ClassNotFoundException ex) {
 // JSR-330 API not available - simply skip.
 }
 }


 private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
 if (ao.getAnnotations().length > 0) { // autowiring annotations have to be local
 for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
 AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao,type);
 if (attributes != null) {
  return attributes;
 }
 }
 }
 return null;
 }

最後將其封裝為AutowiredFieldElement和AutowiredMethodElement物件的list並連同Class一起封裝成InjectionMetadata返回,這就完成了相關注解的收集。

收集完成後在哪裡使用呢?對Bean生命週期熟悉的讀者都知道,之後就會進行依賴注入,自然相關的呼叫就在populateBean這個方法裡:

protected void populateBean(String beanName,@Nullable BeanWrapper bw) {
 
 ......

 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
 MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
 // Add property values based on autowire by name if applicable.
 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
 autowireByName(beanName,bw,newPvs);
 }
 // Add property values based on autowire by type if applicable.
 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
 autowireByType(beanName,newPvs);
 }
 pvs = newPvs;
 }

 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
 boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

 PropertyDescriptor[] filteredPds = null;

 //重點看這個if程式碼塊,重要程度 5
 if (hasInstAwareBpps) {
 if (pvs == null) {
 pvs = mbd.getPropertyValues();
 }
 for (BeanPostProcessor bp : getBeanPostProcessors()) {
 if (bp instanceof InstantiationAwareBeanPostProcessor) {
  InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  // 依賴注入過程,@Autowired的支援
  PropertyValues pvsToUse = ibp.postProcessProperties(pvs,bw.getWrappedInstance(),beanName);
  if (pvsToUse == null) {
  if (filteredPds == null) {
  filteredPds = filterPropertyDescriptorsForDependencyCheck(bw,mbd.allowCaching);
  }

  // 老版本用這個完成依賴注入過程,@Autowired的支援
  pvsToUse = ibp.postProcessPropertyValues(pvs,filteredPds,beanName);
  if (pvsToUse == null) {
  return;
  }
  }
  pvs = pvsToUse;
 }
 }
 }
 if (needsDepCheck) {
 if (filteredPds == null) {
 filteredPds = filterPropertyDescriptorsForDependencyCheck(bw,mbd.allowCaching);
 }
 checkDependencies(beanName,pvs);
 }

 // xml中<property>標籤的依賴注入
 if (pvs != null) {
 applyPropertyValues(beanName,pvs);
 }
 }

mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE

很多讀者包括網上很多文章在看到這個判斷時,都認為自動注入的邏輯就是這裡,但實際上並不是,這裡是自動注入沒錯,但卻是針對以前xml配置,如下:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation=" 
   http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
  default-autowire="byName">
 <bean id="a" class="com.A" autowire="byName"/>
 <bean id="b" class="com.B" autowire="byType"/>
</beans> 

標頭檔案中的default-autowire屬性就是開啟全域性自動注入,而bean標籤上的autowire則是特定針對當前bean的,會覆蓋全域性配置。這樣我們配置後,bean標籤就無需配置prototype子標籤,也能自動注入對應的物件。這些屬性包含了以下幾個值:

no:預設值。表示不進行自動注入。對應BeanDefinition中autowireMode的值為 0。

byName:根據名稱進行自動注入。對應BeanDefinition中autowireMode的值為1。

byType:根據型別進行自動注入,如果容器中找到兩個及以上符合該型別的Bean就將丟擲異常。對應BeanDefinition中autowireMode的值為2。

constructor:等同於byType,只是當指定autowire=”constructor”時表示將通過構造方法根據型別進行自動注入。對應BeanDefinition中autowireMode的值為3。

這就是xml配置中的自動注入,而我們使用@Autowired註解時,BeanDefinition中autowireMode的值為 0,即表示不進行自動注入。插一句題外話,網上很多人在爭論@Autowired是自動注入還是手動注入,我個人認為都算自動注入,不能說它沒有進入這段邏輯就不能叫自動注入,只是它以另外一種方式實現了,至少也沒有讓我們自己手動new並設定屬性。

那這另外一種方式是什麼呢?就是下面這個程式碼乾的事:

if (hasInstAwareBpps) {
 if (pvs == null) {
 pvs = mbd.getPropertyValues();
 }
 for (BeanPostProcessor bp : getBeanPostProcessors()) {
 if (bp instanceof InstantiationAwareBeanPostProcessor) {
 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
 // 依賴注入過程,@Autowired的支援
 PropertyValues pvsToUse = ibp.postProcessProperties(pvs,beanName);
 if (pvsToUse == null) {
 if (filteredPds == null) {
  filteredPds = filterPropertyDescriptorsForDependencyCheck(bw,mbd.allowCaching);
 }

 // 老版本用這個完成依賴注入過程,@Autowired的支援
 pvsToUse = ibp.postProcessPropertyValues(pvs,beanName);
 if (pvsToUse == null) {
  return;
 }
 }
 pvs = pvsToUse;
 }
 }
}

可以看到這裡又是呼叫了InstantiationAwareBeanPostProcessor型別的postProcessProperties和postProcessPropertyValues方法,後者是老版本中的實現,已經廢棄,所以直接看postProcessProperties,還是進入到AutowiredAnnotationBeanPostProcessor類中:

public PropertyValues postProcessProperties(PropertyValues pvs,Object bean,bean.getClass(),pvs);
 try {
 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;
 }

findAutowiringMetadata這個方法不陌生的,剛剛已經分析了,是去收集對應註解並封裝為InjectionMetadata物件放入到快取,這裡就是從快取中拿到值,注入則是通過inject實現的:

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()) {
 for (InjectedElement element : elementsToIterate) {
 if (logger.isTraceEnabled()) {
 logger.trace("Processing injected element of bean '" + beanName + "': " + element);
 }
 if(element.isField) {
 Field field = (Field)element.member;
 System.out.println("==IOC/DI===beanName==" + beanName + "==field[" + field.getName() +"]-> getBean(" + field.getName() + ")");
 }
 element.inject(target,pvs);
 }
 }
}

最後就是呼叫element.inject實現注入,element我們剛剛也看到了,就是AutowiredFieldElement和AutowiredMethodElement,分別實現屬性注入和方法注入,這裡我們看最常用的屬性注入就行了:

protected void inject(Object bean,@Nullable PropertyValues pvs) throws Throwable {
 Field field = (Field) this.member;
 Object value;
 if (this.cached) {
 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,autowiredBeanNames,typeConverter);
 }
 catch (BeansException ex) {
 throw new UnsatisfiedDependencyException(null,new InjectionPoint(field),ex);
 }
 synchronized (this) {
 if (!this.cached) {
 if (value != null || this.required) {
  this.cachedFieldValue = desc;
  registerDependentBeans(beanName,autowiredBeanNames);
  if (autowiredBeanNames.size() == 1) {
  String autowiredBeanName = autowiredBeanNames.iterator().next();
  if (beanFactory.containsBean(autowiredBeanName) &&
  beanFactory.isTypeMatch(autowiredBeanName,field.getType())) {
  this.cachedFieldValue = new ShortcutDependencyDescriptor(
   desc,autowiredBeanName,field.getType());
  }
  }
 }
 else {
  this.cachedFieldValue = null;
 }
 this.cached = true;
 }
 }
 }

 if (value != null) {
 ReflectionUtils.makeAccessible(field);
 field.set(bean,value);
 }
}

這段程式碼整體邏輯比較清晰,首先根據field建立一個依賴物件的抽象DependencyDescriptor物件,然後通過beanFactory.resolveDependency解析拿到對應的例項,最後通過反射注入即可。

因此我們主要看resolveDependency方法中做了什麼:

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 Jsr330Factory().createDependencyProvider(descriptor,requestingBeanName);
 }
 else {
 Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
 descriptor,requestingBeanName);
 if (result == null) {
 result = doResolveDependency(descriptor,requestingBeanName,typeConverter);
 }
 return result;
 }
}

一般情況下,都是走的else分支並呼叫doResolveDependency方法:

public Object doResolveDependency(DependencyDescriptor descriptor,@Nullable TypeConverter typeConverter) throws BeansException {

 InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
 try {
 Object shortcut = descriptor.resolveShortcut(this);
 if (shortcut != null) {
 return shortcut;
 }

 Class<?> type = descriptor.getDependencyType();
 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,descriptor.getMethodParameter()));
 }

 // 有多個實現類需要注入,特指注入的是陣列、集合或者Map
 Object multipleBeans = resolveMultipleBeans(descriptor,typeConverter);
 if (multipleBeans != null) {
 return multipleBeans;
 }

 // 找到依賴物件的所有實現類
 Map<String,Object> matchingBeans = findAutowireCandidates(beanName,descriptor);
 if (matchingBeans.isEmpty()) {
 if (isRequired(descriptor)) {
 raiseNoMatchingBeanFound(type,descriptor.getResolvableType(),descriptor);
 }
 return null;
 }

 String autowiredBeanName;
 Object instanceCandidate;

 // 依賴的物件有多個例項
 if (matchingBeans.size() > 1) {
 // 根據@Primary、@Priority和名稱依次進行匹配注入
 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();
 }

 if (autowiredBeanNames != null) {
 autowiredBeanNames.add(autowiredBeanName);
 }
 // 如果拿到的是class物件,通過getBean例項化返回
 if (instanceCandidate instanceof Class) {
 instanceCandidate = descriptor.resolveCandidate(autowiredBeanName,this);
 }
 Object result = instanceCandidate;
 if (result instanceof NullBean) {
 if (isRequired(descriptor)) {
 raiseNoMatchingBeanFound(type,descriptor);
 }
 result = null;
 }
 if (!ClassUtils.isAssignableValue(type,result)) {
 throw new BeanNotOfRequiredTypeException(autowiredBeanName,instanceCandidate.getClass());
 }
 return result;
 }
 finally {
 ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
 }
}

這裡面首先是通過 getAutowireCandidateResolver().getSuggestedValue(descriptor)拿到@Value註解的值,然後通過TypeConverter進行轉換,預設可轉換的型別是JDK和Spring內建的一些型別,自然不包含我們自定義的類,所以如果不進行擴充套件在@Autowired注入我們自定義類物件時同時使用@Value註解是會報錯的。

接著是呼叫resolveMultipleBeans方法實現對Map、List、陣列等屬性的注入,本質上還是呼叫findAutowireCandidates方法找到所有的實現類的物件裝入對應的集合陣列中,所以直接看findAutowireCandidates:

protected Map<String,Object> findAutowireCandidates(
 @Nullable String beanName,Class<?> requiredType,DependencyDescriptor descriptor) {

 String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
 this,requiredType,true,descriptor.isEager());
 Map<String,Object> result = new LinkedHashMap<>(candidateNames.length);
 
 ......
 
 for (String candidate : candidateNames) {
 if (!isSelfReference(beanName,candidate) && isAutowireCandidate(candidate,descriptor)) {
 addCandidateEntry(result,candidate,descriptor,requiredType);
 }
 }

 ......
 return result;
}

private void addCandidateEntry(Map<String,Object> candidates,String candidateName,DependencyDescriptor descriptor,Class<?> requiredType) {

 if (descriptor instanceof MultiElementDescriptor) {
 Object beanInstance = descriptor.resolveCandidate(candidateName,this);
 if (!(beanInstance instanceof NullBean)) {
 candidates.put(candidateName,beanInstance);
 }
 }
 else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor &&
 ((StreamDependencyDescriptor) descriptor).isOrdered())) {
 Object beanInstance = descriptor.resolveCandidate(candidateName,this);
 candidates.put(candidateName,(beanInstance instanceof NullBean ? null : beanInstance));
 }
 else {
 candidates.put(candidateName,getType(candidateName));
 }
}

首先通過beanNamesForTypeIncludingAncestors方法拿到依賴類所有的實現類的beanName,然後呼叫addCandidateEntry將beanName及對應的例項或者Class物件放入到Map中。

接著回到doResolveDependency方法中:

if (matchingBeans.size() > 1) {
 // 根據@Primary、@Priority和名稱依次進行匹配注入
 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();
}

if (autowiredBeanNames != null) {
 autowiredBeanNames.add(autowiredBeanName);
}
// 如果拿到的是class物件,通過getBean例項化返回
if (instanceCandidate instanceof Class) {
 instanceCandidate = descriptor.resolveCandidate(autowiredBeanName,this);
}
Object result = instanceCandidate;

如果只有一個例項則直接返回該例項,如果實現類有多個則呼叫determineAutowireCandidate進行判斷該使用哪一個例項物件,判斷規則如下:

首先判斷實現類上是否有@Primary註解,找到一個則返回當前例項,找到多個則報錯。

若沒有標註@Primary註解,則判斷是否指定了優先順序,且只能是通過@Priority註解指定的,@Order不支援。

上述都沒有拿到合適的Bean則通過屬性名稱獲取Bean。

拿到對應的例項後,最後進行反射注入即可。以上就是@Autowired的實現細節。

總結

本篇從原始碼角度詳細分析了@Autowired的實現細節,只有真正閱讀了原始碼才能瞭解更多的細節,在開發中更加清楚如何注入多個例項以及如何指定注入的優先順序,同時在面試中也能更有理有據,而不是統一的大眾回答,先根據byType,再根據byName。另外對於方法注入和@Resource註解的處理本篇沒有涉及,但是相信看完本文讀者自己也能輕鬆分析這部分原始碼。