Spring中Bean的實例化與DI的過程

引言

前文咱們介紹了關於如何學習Spring的源碼以及解析了spring中加載配置文件註冊Beandefinition的過程。今天咱們繼續學習DI的過程。java

建立實例和DI過程

IOC和DI都是對spring容器特性的描述。IOC指的是將實例的生命週期交給第三方管理(spring)。而DI的側重點在於某一個類依賴了其餘的實例,將實例注入到依賴它的實例的過程。因此能夠很明顯的看出來DI是發生在類實例已經實例化完成以後的。spring

###建立實例api

BeanDefinition

BeanDefinition是對bean屬性的定義,包含了bean的狀態的屬性,如bean的Class對象,單例仍是原型等。緩存

Beandefinition

上圖中是BeanDefinition定義的方法,能夠看出其中包括建立Bean的工廠類名稱和bean的狀態單例,懶加載等。bash

其中大多數方法都很容易理解,有幾個屬性這裏須要解釋下。markdown

dependsOn

dependsOn是指當前Beandefinition所表示的Bean依賴了其餘那些bean(不包括基本數據類型),這裏依賴的bean並不須要在當前Bean中聲明,因此不能經過依賴注入完成,而是須要顯示的定義。session

autowireCandidate

autowireCandidate用來表示當前bean是否能夠被注入到其餘實例中。mvc

上面的內容均可以經過xml配置或者註解來配置。app

xmljvm

<bean scope="singleton" autowire-candidate="true" init-method="" factory-method="" lazy-init="true" >
    </bean>
複製代碼

註解

public class JavaBean {
    
    public void init(){
        //init
    }

    public void destroy(){
        //destroy
    }
    
    @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public JavaBean getEntity(){
        return new JavaBean();
    }
}
複製代碼
繼承體系

BeanDefinition繼承體系

在上圖中實際實際被用來實現Beandefinition的類是RootBeanDefinitionChildBeanDefinitionGenericBeanDefinition。其中GenericBeanDefinition是在spring2.5之後纔出現的,spring2.5之後都建議使用GenericBeanDefinition。可是因爲之前的代碼都是使用RootBeanDefinitionChildBeanDefinition,因此咱們也還能看到RootBeanDefinitionChildBeanDefinition這些類。

大致流程

同IOC同樣在閱讀源碼前先來看看一DI的大致流程。

DI流程

refresh()

在閱讀IOC相關實現的時候,除開構造函數外refresh()就是咱們最初的入口,當時只是看了其中的部分代碼。實際上refresh()貫穿了spring啓動的整個階段。當refresh()方法執行完成時基本就表明spring正常啓動了。在DI篇咱們來繼續看refresh()的其餘的一些代碼。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
		    //讀取配置文件 註冊Beandefinition
			prepareRefresh();
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			prepareBeanFactory(beanFactory);

			try {

				postProcessBeanFactory(beanFactory);
				invokeBeanFactoryPostProcessors(beanFactory);

				registerBeanPostProcessors(beanFactory);

				initMessageSource();

				initApplicationEventMulticaster();

				onRefresh();

				registerListeners();

				finishBeanFactoryInitialization(beanFactory);

				finishRefresh();
			}catch (BeansException ex) {
				logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);

				destroyBeans();

				cancelRefresh(ex);
				throw ex;
			}
		}
	}
複製代碼

BeanFactoryPostProcessor和BeanPostProcessor

在進行bean的實例化以前會先執行BeanFactoryPostProcessor和註冊BeanPostProcessor

BeanFactoryPostProcessorBeanPostProcessor這兩個接口爲Spring的Bean後置處理器接口,做用是爲Bean的初始化先後提供可擴展的空間。

BeanFactoryPostProcessor

public interface BeanFactoryPostProcessor {
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
複製代碼

BeanFactoryPostProcessor能夠對BeanDefinition進行處理。BeanFactoryPostProcessor在容器實際實例化任何其它的bean以前讀取bean的元數據,而且能夠對其進行修改修改。用於在執行實例化bean以前進行調用。

BeanPostProcessor

public interface BeanPostProcessor {

	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
複製代碼

實現BeanPostProcessor接口能夠在Bean初始化的先後作一些自定義的操做,可是不可以直接操做BeanDefinition元數據。

BeanFactoryPostProcessorBeanPostProcessor都是spring留給咱們進行擴展的類。經過實現這兩個接口咱們能夠在bean的實例化過程當中添加一些自定義的操做。而須要注意的是這兩個接口雖然都提供了擴展bean實例化的功能,但二者確實徹底不一樣的:

  • BeanFactoryPostProcessor是在全部的bean都未開始實例化前調用,其能夠拿到容器中全部的Beandefinition,因此能夠在bean實例化前直接修改bean定義的元數據。
  • BeanPostProcessor裏的實例化先後指的是調用init(init-method)方法先後,這時實際上bean已經開始了實例化(詳細的能夠參考類的實例化全過程),這時取到的僅僅是某一指定類的實例。即便進行修改也只是修改當前這一實例,而沒法對bean的元數據修改。

因爲postProcessor可能會在bean的實例化以前進行調用,因此在實例化前context確定須要先拿到postProcessor,這也就能夠解釋上面的代碼中在解析完配置文件後就開始註冊BeanFactoryPostProcessorBeanPostProcessor

listener

//tood

具體的關於postProcessor和Listener相關會在將總體流程理順後再詳細介紹。

finishBeanFactoryInitialization(ConfigurableListableBeanFactory)

finishBeanFactoryInitialization方法是對bean進行實例化的入口。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}
        
		beanFactory.setTempClassLoader(null);
		//緩存bean定義
		beanFactory.freezeConfiguration();
		beanFactory.preInstantiateSingletons();
	}
複製代碼

方法首先查找是否開啓了註冊conversionService,conversionService是用於進行兩個類轉換的,例如以前說過了Environment類就依賴該實例將定義的變量轉換爲相應的類型。

若是要開啓註冊conversionService,能夠在配置文件中配置。

<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
	<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
	//property
	</bean>
複製代碼

接下來的代碼是從bean定義中獲取LoadTimeWeaverAware類型優先進行實例化。LoadTimeWeaverAware做用是當類被加載進jvm是動態的轉換類。之因此優先實例化這些類是由於在實例化其餘類時可能會使用到這些類,好比jpa就極度依賴這些功能。

preInstantiateSingletons()

public void preInstantiateSingletons() throws BeansException {
		List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

		for (String beanName : beanNames) {
		    //獲取bean定義
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//抽象類沒法實例化
			//非單例和懶加載在須要時才實例化
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
				    //獲取factoryBean的實例
					final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
							@Override
							public Boolean run() {
								return ((SmartFactoryBean<?>) factory).isEagerInit();
							}
						}, getAccessControlContext());
					}else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					if (isEagerInit) {
						getBean(beanName);
					}
				}else {
					getBean(beanName);
				}
			}
		}

		// 實現了SmartInitializingSingleton接口的回調方法
		// SmartInitializingSingleton接口同InitializingBean接口相似都是用於在建立bean時進行一些後置的操做 
		// 不一樣之處在於InitializingBean是在每個實例化的過程當中進行調用 而SmartInitializingSingleton是在全部的單例bean被實例化後再refresh中進行回調
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged(new PrivilegedAction<Object>() {
						@Override
						public Object run() {
							smartSingleton.afterSingletonsInstantiated();
							return null;
						}
					}, getAccessControlContext());
				}else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}
複製代碼

preInstantiateSingletons經過一個for循環來實例化全部註冊到容器中的bean定義所表明的的bean。

在肯定好每個beanName所表明的的bean確實須要實例化後首先檢查當前beanName是否實現了接口 FactoryBeanFactoryBean是一種產生bean的bean,至關於一個bean工廠。實現FactoryBean接口容許咱們生產一個具備特色類型和參數的bean,其本質上和經過xml配置實例化的bean沒有區別,好處在於對於複雜對象能夠代替xml中繁雜的配置項,僅經過java代碼實現。

而因爲FactoryBean自己首先是一個bean,因此咱們也能夠在ioc容器中獲取該bean的實例。若是咱們經過getBean(beanName)方法獲取的其實是FactoryBean產生的實例類型,想要獲取FactoryBean的實例須要使用getBean("&" + beanName)

getBean(String)

getBean是一個重載方法,主要仍是調用doGetBean()方法實現功能。

protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {
        //取該beanName在容器中保存的name
        //好比上面介紹的factoryBean會加一個& 以及給bean配置的別名等
		final String beanName = transformedBeanName(name);
		Object bean;
        //嘗試從保存bean的容器中取,若是已經存在則不用再次實例化
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}else {
            //對於非單例bean 若是該bean正在被建立而又嘗試再次建立則會直接拋出異常
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
			    //!containsBeanDefinition(beanName)表示從當前容器中沒有找到匹配的BeanDefinition 嘗試從父容器中查找
				String nameToLookup = originalBeanName(name);
				if (args != null) {
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}else {
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			if (!typeCheckOnly) {
			    //標記當前beanName所表示的bean正在被建立或已經被建立
				markBeanAsCreated(beanName);
			}

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				//這一步根據其實現貌似主要是檢查當前BeanDefinition表示的bean是不是一個抽象類,可是前面已經檢查過了 這裏再次檢查貌似意義不大
				checkMergedBeanDefinition(mbd, beanName, args);
				
				//檢查是否配置了bean的依賴 若是存在則須要先實例化被依賴的bean
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dependsOnBean : dependsOn) {
						if (isDependent(beanName, dependsOnBean)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
						}
						registerDependentBean(dependsOnBean, beanName);
						getBean(dependsOnBean);
					}
				}

				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}else if (mbd.isPrototype()) {
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
							@Override
							public Object getObject() throws BeansException {
								beforePrototypeCreation(beanName);
								try {
									return createBean(beanName, mbd, args);
								}
								finally {
									afterPrototypeCreation(beanName);
								}
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; " +
								"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
			try {
				return getTypeConverter().convertIfNecessary(bean, requiredType);
			}catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type [" +
							ClassUtils.getQualifiedName(requiredType) + "]", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}
複製代碼

方法中的try-catch塊用於建立bean實例,代碼不少,不過只是根據bean的做用範圍來進行建立如Singleton,prototype或者session等。建立bean的過程大同小異,區別僅在與實例保存的地方。單例bean被保存在一個map中,整個程序運行期間有效。原型bean保存在另外的容器中,每一次使用時須要從新建立。

以單例bean建立過程爲例,主要實現過程都在getSingleton(...)方法中了。getSingleton(...)的主要功能就是檢查bean是否已經建立,若是沒建立就進行建立而後保存到容器中。建立bean的過程由一個匿名內部類實現。

createBean(String beanName, RootBeanDefinition mbd, Object[] args)

protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
			throws BeanCreationException {

		resolveBeanClass(mbd, beanName);
		try {
			mbd.prepareMethodOverrides();
		}catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
		    //首先嚐試執行BeanPostProcessor,若是存在後置處理器 那麼首先實例化bean執行處理器
			Object bean = resolveBeforeInstantiation(beanName, mbd);
			if (bean != null) {
				return bean;
			}
		}catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}
        //不存在後置處理器或者存在的執行處理器過程建立實例失敗或沒有建立實例的動做則執行下面的方法
		Object beanInstance = doCreateBean(beanName, mbd, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
複製代碼

上面方法中有這樣一句mbd.prepareMethodOverrides()methodOverrides實際上市BeanDefinition中的一個屬性。其主要用於記錄在配置文件中lookup-method和replaced-method參數設置的值。詳情能夠看這裏:methodOverrides

doCreateBean(...)

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {

		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
		    //若是已經實例化須要從新實例化則從緩存中刪除 從新設置
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		//more code
	}
複製代碼

方法開頭顯示建立了一個BeanWrapper的對象,BeanWrapper至關於一個代理器,Spring委託BeanWrapper來完成bean內部屬性的初始化。

上述方法代碼不少,在建立階段只須要關注前幾行。若是該bean的實例未被建立則直接建立一個。建立的方法有createBeanInstance完成。

createBeanInstance(...)

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
		Class<?> beanClass = resolveBeanClass(mbd, beanName);
        //判斷當前bean類是否被定義爲public 非public的類沒法在其餘類中實例化
		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}
		if (mbd.getFactoryMethodName() != null)  {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				return instantiateBean(beanName, mbd);
			}
		}

		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
			return autowireConstructor(beanName, mbd, ctors, args);
		}
		return instantiateBean(beanName, mbd);
	}
複製代碼

該方法先是嘗試查看是否配置了工廠方法,若是存在工廠方法則由工廠方法進行建立。

接下來的幾行代碼是用來提高性能的。spring在建立實例後會將建立該實例的constructor方法緩存,這樣下一次須要建立該bean時直接取出構造方法建立便可不須要再從新解析一次。

若是沒有工廠方法而且構造方法也沒有緩存,同時沒有找到有參的構造函數,那麼會經過放射調用類的默認無參構造函數。

instantiateBean(String, RootBeanDefinition)

該實例化方法沒有太多解析的必要,基本就是經過反射的原理獲取無參構造函數,經過構造函數來實例化類。

DI

到這裏爲止建立一個實例的過程就完成了,接下來就是檢查該實例是否須要被注入其餘的屬性了。

回到doCreateBean(...)

前面在建立bean實例時調用到了doCreateBean(...)方法,在建立好實例後的後續功能也依賴於該方法。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
        // other-code
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
				exposedObject = initializeBean(beanName, exposedObject, mbd);
			}
		} catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}else {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}
		// other-code
		return exposedObject;
	}
複製代碼

在DI階段咱們須要關注的就上上面的代碼,首先是經過populateBean方法對在配置文件中配置的property屬性進行設置值。

populateBean顧名思義就是對bean中的屬性添加數據。populateBean中實際上是經過後置處理器來進行屬性的設置,主要的代碼以下:

PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
			if (pvs == null) {
				return;
			}
		}
	}
}
複製代碼

spring中默認註冊瞭如下幾種beanPostProcessor,以下:

beanPostProcessor

每個beanPostProcessor都會在實例化先後相應的地方進行調用。在這裏咱們須要關注的是AutowiredAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor這幾個註解。

顧名思義這幾個beanPostProcessor都是用來處理註解的,對應用來處理@Autowired,@Required,@Common幾個註解。

這裏以@Autowored的處理爲例。

AutowiredAnnotationBeanPostProcessor

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

		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass());
		try {
			metadata.inject(bean, beanName, pvs);
		}catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}
	
	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 annotation = findAutowiredAnnotation(field);
				if (annotation != null) {
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation is not supported on static fields: " + field);
						}
						continue;
					}
					boolean required = determineRequiredStatus(annotation);
					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對象。解析的過程經過findAutowiringMetadata(String beanName, Class<?> clazz)完成,但實際上主要仍是經過上面的buildAutowiringMetadata(Class<?> clazz)完成。

方法比較簡單,首先就是遍歷bean的全部字段(Field),經過反射的方法查找字段上的註解,若是存在匹配的註解(AutowiredAnnotationBeanPostProcessor匹配的就是@Autowired)。若是存在該註解就將這個字段記錄表示須要進行注入。

當將字段遍歷完成後就取出全部的方法,查找方法上是否有該註解,若是存在的話同理記錄下該方法。

對於被記錄下的字段或者方法會被封裝成一個InjectedElement對象。經過該對象的inject方法完成注入工做。

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();
				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);
		}
	}
}
複製代碼

剛方法整體來講比較簡單,首先是查詢當前bean的依賴是否已經被緩存,若是緩存了則從緩存中取便可。

若是是第一次解析則從beanfactory中獲取相應的依賴屬性。

synchronized代碼塊主要就是將解析後的依賴的值緩存起來,創建當前bean和其依賴的屬性之間的關係。當下一次建立該類型的bean時能夠直接使用不需從新解析。

而真正的屬性注入是依賴着幾行代碼:

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

上面的代碼沒有任何的難度,就是對JDK中反射的api的使用。

基本上後面就是重複這個過程對bean的屬性進行注入,在這一過程當中最重要的就是beanPostProcessor,注入都已依賴這一組完成的。

相關文章
相關標籤/搜索