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


前言

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

正文

在Spring Bean的整個創建過程中會調用很多BeanPostProcessor接口的的實現類:
在這里插入圖片描述
上圖是我整理的Spring Bean的創建過程及整個過程中各個BeanPostProcessor和回調的調用,右邊相同顏色的連線代表是同一組調用,主要看到AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor,前者就是支持 @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, Class<?> beanType, String beanName) {
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, 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;
	}

最后將其封裝為AutowiredFieldElementAutowiredMethodElement對象的list並連同Class一起封裝成InjectionMetadata返回,這就完成了相關注解的收集。
收集完成后在哪里使用呢?對Bean生命周期熟悉的讀者都知道,之后就會進行依賴注入,自然相關的調用就在populateBean這個方法里:

	protected void populateBean(String beanName, RootBeanDefinition mbd, @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, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, 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, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		// xml中<property>標簽的依賴注入
		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, 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, bw.getWrappedInstance(), beanName);
			if (pvsToUse == null) {
				if (filteredPds == null) {
					filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
				}

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

可以看到這里又是調用了InstantiationAwareBeanPostProcessor類型的postProcessPropertiespostProcessPropertyValues方法,后者是老版本中的實現,已經廢棄,所以直接看postProcessProperties,還是進入到AutowiredAnnotationBeanPostProcessor類中:

	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		InjectionMetadata metadata = findAutowiringMetadata(beanName, 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, beanName, pvs);
		}
	}
}

最后就是調用element.inject實現注入,element我們剛剛也看到了,就是AutowiredFieldElementAutowiredMethodElement,分別實現屬性注入和方法注入,這里我們看最常用的屬性注入就行了:

protected void inject(Object bean, @Nullable String beanName, @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, beanName, autowiredBeanNames, typeConverter);
		}
		catch (BeansException ex) {
			throw new UnsatisfiedDependencyException(null, beanName, 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, autowiredBeanNames, typeConverter);
		}
		return result;
	}
}

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

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
		@Nullable Set<String> autowiredBeanNames, @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, type, descriptor.getMethodParameter()));
		}

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

		// 找到依賴對象的所有實現類
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, 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, 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);
	}
}

這里面首先是通過 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, requiredType, this);
		if (!(beanInstance instanceof NullBean)) {
			candidates.put(candidateName, beanInstance);
		}
	}
	else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor &&
			((StreamDependencyDescriptor) descriptor).isOrdered())) {
		Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, 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, type, this);
}
Object result = instanceCandidate;

如果只有一個實例則直接返回該實例,如果實現類有多個則調用determineAutowireCandidate進行判斷該使用哪一個實例對象,判斷規則如下:

  • 首先判斷實現類上是否有@Primary注解,找到一個則返回當前實例,找到多個則報錯。
  • 若沒有標注@Primary注解,則判斷是否指定了優先級,且只能是通過@Priority注解指定的,@Order不支持。
  • 上述都沒有拿到合適的Bean則通過屬性名稱獲取Bean。

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

總結

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM