Spring註解@Autowired源碼分析

AutowiredAnnotationBeanPostProcessor是Spring的後置處理器,專門處理@Autowired和@Value註解。java

1、觸發方式

  • Spring容器在每一個Bean實例化以後,調用AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法。
  • Spring在每一個Bean實例化的時候,調用populateBean進行屬性注入的時候,即調用postProcessPropertyValues方法。

2、構造函數

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.
	}
	}

3、注入的方法

//處理類中的屬性,屬性注入
	@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的屬性進行自動注入
		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。這裏的邏輯仍是有些多的,以後會專門介紹,這裏就很少說了。緩存

直接看具體的注入邏輯:app

//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);ide

//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()的原始方法,它還有兩個子類本身實現的方法,如圖:函數

從方法名稱能夠看出,一個是對字段進行注入,一個是對方法進行注入。而且這兩個方法都是AutowiredAnnotationBeanPostProcessor具體的實現。post

3.一、字段注入

咱們先來看下對字段的注入: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;
	}
	}

進行跟蹤:lua

//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 {
		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()) {
			//是不是必須的
			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,若是有多個,則挑選出最優的那一個。

下面來看下具體邏輯。

3.1.一、<1>處:@Autowired注入集合數組

先來看下@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;
	}
	}

3.1.二、<2>處:@Autowired注入非集合數組

//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

<3>處:多個候選者中挑選出最優解

若是根據類型從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註解來擇取最優解
  • 根據@Order,@PriorityOrder,及實現Order接口的序號來擇取最優解
  • 根據Spring默認規則

咱們逐一分析這幾個步驟,先看第一個:
根據@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字段注入的源碼就分析完畢了。

接下來咱們看下方法注入:

3.二、方法注入

//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,利用反射注入到字段中。

相關文章
相關標籤/搜索