Spring源碼-IOC容器(十)-@Autowired解析

Spring IOC容器 源碼解析系列,建議你們按順序閱讀,歡迎討論spring

(spring源碼均爲4.1.6.RELEASE版本)緩存

  1. Spring源碼-IOC容器(一)-構建簡單IOC容器
  2. Spring源碼-IOC容器(二)-Bean的定位解析註冊
  3. Spring源碼-IOC容器(三)-GetBean
  4. Spring源碼-IOC容器(四)-FactoryBean
  5. Spring源碼-IOC容器(五)-Bean的初始化
  6. Spring源碼-IOC容器(六)-bean的循環依賴
  7. Spring源碼-IOC容器(七)-ApplicationContext
  8. Spring源碼-IOC容器(八)-NamespaceHandler與自定義xml
  9. Spring源碼-IOC容器(九)-Component-Scan源碼解析
  10. Spring源碼-IOC容器(十)-@Autowired解析

1.前言

部門有實習生來的時候,都會先了解系統的基本架構,再寫一個基本的demo。一般強調的就是新建的類上要加@Controller或@Service,而類中的引用的其餘對象的屬性上加上@Autowired,而後寫點增刪改查就ok了。通常初學一個框架時只需知道如何使用,但想要用的好,就必需要深刻了解其原理。所謂知其然,也要知其因此然。在Spring使用註解後,由於其自己就是非侵入式的設計,致使使用的人能感知到的就是幾個註解。這樣的框架的設計天然是極好的,對於使用的人來講,更是值得學習。數據結構

@Controller和@Service都是繼承自@Component,只是分別標識Controller層和Service層,用於對類進行分類。@Component做爲Spring的類掃描的默認註解,在Spring源碼-IOC容器(九)-Component-Scan源碼解析中已介紹過。而@Autowired能夠說是Spring依賴注入的最重要的註解,本章就來詳細解析它的使用原理。架構

2.使用範圍及方式

@Autowired最經常使用的方式就是放在屬性或setter方法上,而其還能放在構造函數以及非setter方法的任意方法上。app

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

	/**
	 * Declares whether the annotated dependency is required.
	 * <p>Defaults to {@code true}.
	 */
	boolean required() default true;

}

能夠看到支持的目標包括構造函數,屬性,方法,也能夠被做爲元註解。這裏須要強調的有兩個:框架

  1. 屬性和方法能夠爲private
  2. 無參的構造方法上使用會報錯,緣由在後面解析。

@Autowired是根據對象類型來進行匹配的,若是想經過指定具體的bean的名稱,可使用@Qualifier。@Autowired只有required屬性能夠設置,默認爲true,即默認必須能匹配到相應的bean,不然就會報出NoSuchBeanDefinitionException異常。若是容許依賴注入失敗,則能夠設置required=false。ide

@Autowired的解析器是AutowiredAnnotationBeanPostProcessor,它是BeanPostProcessor後置處理器的子類。若是經過BeanFactory的啓動方式,須要手動注入。函數

xml文件post

<bean id="autowiredAnnotationBeanPostProcessor" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

而且經過學習

beanFactory.addBeanPostProcessor((BeanPostProcessor) beanFactory.
            getBean("autowiredAnnotationBeanPostProcessor"));

添加到beanPostProcessor集合中。

但一般狀況下component-scan掃描的配置處理中默認就加載了AutowiredAnnotationBeanPostProcessor。

<context:component-scan base-package=".."/>

若是不使用component-scan的掃描配置,能夠經過

<context:annotation-config/>

來默認配置。

3.原理及源碼

在Spring的bean實例化過程當中有許多BeanPostProcessor擴展點,支持內置的以及用戶自定義的BeanPostProcessor對bean的實例化進行干預和操做。BeanPostProcessor接口自己只支持bean的初始化先後的擴展,但它的子接口則增長了更多擴展點。

  1. BeanPostProcessor
    • postProcessBeforeInitialization 初始化前擴展
    • postProcessAfterInitialization 初始化後擴展
  2. InstantiationAwareBeanPostProcessor
    • postProcessBeforeInstantiation 實例化前擴展
    • postProcessAfterInstantiation 實例化後擴展
    • postProcessPropertyValues 依賴注入前擴展
  3. MergedBeanDefinitionPostProcessor
    • postProcessMergedBeanDefinition 實例化後針對BeanDefinition的擴展
  4. SmartInstantiationAwareBeanPostProcessor(InstantiationAwareBeanPostProcessor的子接口,還有兩個方法這裏沒有列舉)
    • determineCandidateConstructors 實例化時返回構造函數候選者

對於AutowiredAnnotationBeanPostProcessor,先來看它的實現

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
	implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware

它實現了MergedBeanDefinitionPostProcessor接口,而繼承的InstantiationAwareBeanPostProcessorAdapter實際上是SmartInstantiationAwareBeanPostProcessor接口的默認實現類。因此基本支持了全部的擴展點,但不少都是繼承的默認方法,主要實現的有三個方法:

  1. determineCandidateConstructors
  2. postProcessMergedBeanDefinition
  3. postProcessPropertyValues

第一個方法支撐了@Autowired做用於構造函數,第二和三方法支撐了@Autowired做用於屬性和方法。

1.構造函數

在AbstractAutowireCapableBeanFactory中的createBeanInstance方法中,對bean進行實例化操做。若是沒有經過xml指定構造函數或工廠方法,則會判斷是否有InstantiationAwareBeanPostProcessor註冊到容器中,並判斷是否爲其子接口SmartInstantiationAwareBeanPostProcessor的實現類,而後調用determineCandidateConstructors方法返回構造函數候選者集合。

AbstractAutowireCapableBeanFactory.createBeanInstance()

// Need to determine the constructor...
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
		mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
		mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
	return autowireConstructor(beanName, mbd, ctors, args);
}

protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(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;
}

此時就進入AutowiredAnnotationBeanPostProcessor的determineCandidateConstructors方法中

public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeansException {
	// 解析Lookup註解,並設置到BeanDefinition中
	if (!this.lookupMethodsChecked.contains(beanName)) {
		ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
			@Override
			public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
				Lookup lookup = method.getAnnotation(Lookup.class);
				if (lookup != null) {
					LookupOverride override = new LookupOverride(method, lookup.value());
					try {
						RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
						mbd.getMethodOverrides().addOverride(override);
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanCreationException(beanName,
								"Cannot apply @Lookup to beans without corresponding bean definition");
					}
				}
			}
		});
		this.lookupMethodsChecked.add(beanName);
	}

	// Quick check on the concurrent map first, with minimal locking.
	Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
	if (candidateConstructors == null) {
		synchronized (this.candidateConstructorsCache) {
			candidateConstructors = this.candidateConstructorsCache.get(beanClass);
			if (candidateConstructors == null) {
				// 拿到全部public的構造函數
				Constructor<?>[] rawCandidates = beanClass.getDeclaredConstructors();
				List<Constructor<?>> candidates = new ArrayList<Constructor<?>>(rawCandidates.length);
				Constructor<?> requiredConstructor = null;
				Constructor<?> defaultConstructor = null;
				for (Constructor<?> candidate : rawCandidates) {
					// 尋找構造函數上的@Autowired註解
					AnnotationAttributes ann = findAutowiredAnnotation(candidate);
					if (ann != null) {
						// 只容許有一個required=true的@Autowired
						if (requiredConstructor != null) {
							throw new BeanCreationException(beanName,
									"Invalid autowire-marked constructor: " + candidate +
									". Found constructor with 'required' Autowired annotation already: " +
									requiredConstructor);
						}
						// 無參構造函數上設置@Autowired拋出異常
						if (candidate.getParameterTypes().length == 0) {
							throw new IllegalStateException(
									"Autowired annotation requires at least one argument: " + candidate);
						}
						boolean required = determineRequiredStatus(ann);
						if (required) {
							if (!candidates.isEmpty()) {
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructors: " + candidates +
										". Found constructor with 'required' Autowired annotation: " +
										candidate);
							}
							requiredConstructor = candidate;
						}
						candidates.add(candidate);
					}
					else if (candidate.getParameterTypes().length == 0) {
						defaultConstructor = candidate;
					}
				}
				if (!candidates.isEmpty()) {
					// Add default constructor to list of optional constructors, as fallback.
					if (requiredConstructor == null) {
						if (defaultConstructor != null) {
							candidates.add(defaultConstructor);
						}
						else if (candidates.size() == 1 && logger.isWarnEnabled()) {
							logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
									"': single autowire-marked constructor flagged as optional - this constructor " +
									"is effectively required since there is no default constructor to fall back to: " +
									candidates.get(0));
						}
					}
					candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
				}
				else {
					candidateConstructors = new Constructor<?>[0];
				}
				this.candidateConstructorsCache.put(beanClass, candidateConstructors);
			}
		}
	}
	return (candidateConstructors.length > 0 ? candidateConstructors : null);
}

基本步驟爲:

  1. 查找是否有Lookup註解,若是有,設置到BeanDefinition的methodOverrides中
  2. 從Class對象中獲取全部public構造方法
  3. 返回全部設置@Autowired註解的構造方法(只能有一個required=true)

返回的構造函數集合根據必定的策略找到最佳的一個,而後經過newInstance方法實例化bean對象。

2.屬性及方法

在bean實例化完成後,MergedBeanDefinitionPostProcessor的擴展點支持對BeanDefinition進行處理。

AbstractAutowireCapableBeanFactory.doCreateBean()

// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
	if (!mbd.postProcessed) {
		applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
		mbd.postProcessed = true;
	}
}

而在AutowiredAnnotationBeanPostProcessor的實現中,經過查找並組裝全部有@Autowired的屬性及方法。

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	if (beanType != null) {
		// 查找全部@Autowired的屬性和方法,組裝成InjectionMetadata,存放到Map中
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}
}

在findAutowiringMetadata方法中,對屬性和方法分開解析並組裝不一樣的數據結構中,AutowiredFieldElement和AutowiredMethodElement。

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
	// Fall back to class name as cache key, for backwards compatibility with custom callers.
	// 緩存key爲bean名稱
	String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
	// Quick check on the concurrent map first, with minimal locking.
	// 先從Map中查詢是否存在
	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);
				}
				try {
					// 構建元數據數據結構
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
				catch (NoClassDefFoundError err) {
					throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() +
							"] for autowiring metadata: could not find class that it depends on", err);
				}
			}
		}
	}
	return metadata;
}

// 根據Class對象,對屬性和方法分別進行組裝
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
	LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
	Class<?> targetClass = clazz;

	do {
		LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<InjectionMetadata.InjectedElement>();
		// 屬性
		for (Field field : targetClass.getDeclaredFields()) {
			AnnotationAttributes ann = findAutowiredAnnotation(field);
			if (ann != null) {
				if (Modifier.isStatic(field.getModifiers())) {
					if (logger.isWarnEnabled()) {
						logger.warn("Autowired annotation is not supported on static fields: " + field);
					}
					continue;
				}
				boolean required = determineRequiredStatus(ann);
				currElements.add(new AutowiredFieldElement(field, required));
			}
		}

		// 方法
		for (Method method : targetClass.getDeclaredMethods()) {
			Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
			if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
				continue;
			}
			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);
					}
					continue;
				}
				if (method.getParameterTypes().length == 0) {
					if (logger.isWarnEnabled()) {
						logger.warn("Autowired annotation should be used on methods with actual 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);
}

這樣在實例化後,bean中全部@Autowired的屬性和方法都被組裝成InjectionMetadata存儲到以bean名稱爲key的Map中。

AbstractAutowireCapableBeanFactory的populateBean方法用來對bean進行依賴注入,而在真正的依賴注入前,一樣檢查是否有InstantiationAwareBeanPostProcessor,並調用postProcessPropertyValues方法對bean的依賴進行外部擴展處理。

AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues也很是清晰。

public PropertyValues postProcessPropertyValues(
		PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

	// 再次查找全部@Autowired的屬性和方法,若是有緩存,直接從緩存中獲取
	InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
	try {
		// 執行屬性的依賴注入和方法的執行
		metadata.inject(bean, beanName, pvs);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
	}
	return pvs;
}

findAutowiringMetadata在上面已經介紹過了,此時直接從Map的緩存中獲取便可。主要來看InjectionMetadata的inject方法。

public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
	Collection<InjectedElement> elementsToIterate =
			(this.checkedElements != null ? this.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);
		}
	}
}

遍歷取出全部的InjectedElement,包括屬性和方法,分別執行inject方法。

1.AutowiredFieldElement

主要的操做是

  1. 經過beanFactory的resolveDependency方法從beanFactory中匹配相同類型的BeanDefition,並經過getBean方法實例化對象,若是有多個匹配項,默認返回第一個。

  2. 向容器註冊依賴關係,並緩存RuntimeBeanReference類型的FieldValue

  3. 經過反射注入屬性值

    protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
     	Field field = (Field) this.member;
     	try {
     		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<String>(1);
     			TypeConverter typeConverter = beanFactory.getTypeConverter();
     			// 從beanFactory匹配類型相同的bean對象
     			value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
     			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)) {
     								if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
     									this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName);
     								}
     							}
     						}
     					}
     					else {
     						this.cachedFieldValue = null;
     					}
     					this.cached = true;
     				}
     			}
     		}
     		if (value != null) {
     			// 反射注入屬性值
     			ReflectionUtils.makeAccessible(field);
     			field.set(bean, value);
     		}
     	}
     	catch (Throwable ex) {
     		throw new BeanCreationException("Could not autowire field: " + field, ex);
     	}
     }

    }

2.AutowiredMethodElement

方法的操做同屬性相近,只是根據方法中的每一個參數的類型去beanFactory中去匹配bean對象。

  1. 遍歷方法中的全部參數,按照類型從beanFactory中匹配相應的BeanDefition並實例化,過程同AutowiredFieldElement中一致

  2. 註冊對象依賴關係,方法中全部的參數都是bean的依賴方,而後每一個參數分別緩存爲RuntimeBeanReference類型的結構。

  3. 調用反射方法執行方法

    protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
     	if (checkPropertySkipping(pvs)) {
     		return;
     	}
     	Method method = (Method) this.member;
     	try {
     		Object[] arguments;
     		if (this.cached) {
     			// Shortcut for avoiding synchronization...
     			arguments = resolveCachedArguments(beanName);
     		}
     		else {
     			Class<?>[] paramTypes = method.getParameterTypes();
     			arguments = new Object[paramTypes.length];
     			DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
     			Set<String> autowiredBeanNames = new LinkedHashSet<String>(paramTypes.length);
     			TypeConverter typeConverter = beanFactory.getTypeConverter();
     			// 遍歷方法中的參數,查找對應的bean實例
     			for (int i = 0; i < arguments.length; i++) {
     				MethodParameter methodParam = new MethodParameter(method, i);
     				DependencyDescriptor desc = new DependencyDescriptor(methodParam, this.required);
     				desc.setContainingClass(bean.getClass());
     				descriptors[i] = desc;
     				Object arg = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
     				if (arg == null && !this.required) {
     					arguments = null;
     					break;
     				}
     				arguments[i] = arg;
     			}
     			synchronized (this) {
     				if (!this.cached) {
     					if (arguments != null) {
     						this.cachedMethodArguments = new Object[arguments.length];
     						for (int i = 0; i < arguments.length; i++) {
     							this.cachedMethodArguments[i] = descriptors[i];
     						}
     						// 註冊全部的參數爲bean的依賴方
     						registerDependentBeans(beanName, autowiredBeanNames);
     						if (autowiredBeanNames.size() == paramTypes.length) {
     							Iterator<String> it = autowiredBeanNames.iterator();
     							for (int i = 0; i < paramTypes.length; i++) {
     								String autowiredBeanName = it.next();
     								if (beanFactory.containsBean(autowiredBeanName)) {
     									if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
     										this.cachedMethodArguments[i] = new RuntimeBeanReference(autowiredBeanName);
     									}
     								}
     							}
     						}
     					}
     					else {
     						this.cachedMethodArguments = null;
     					}
     					this.cached = true;
     				}
     			}
     		}
     		if (arguments != null) {
     			// 反射執行方法
     			ReflectionUtils.makeAccessible(method);
     			method.invoke(bean, arguments);
     		}
     	}
     	catch (InvocationTargetException ex) {
     		throw ex.getTargetException();
     	}
     	catch (Throwable ex) {
     		throw new BeanCreationException("Could not autowire method: " + method, ex);
     	}
     }

這樣全部的@Autowired設置都執行完成,註解方式的依賴注入就經過BeanPostProcessor這種擴展點的方式完成。

相關文章
相關標籤/搜索