《Spring源碼深度解析》- 5BeanFactory的加載

5 BeanFactory的加載

org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)java

@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		/* (一). 轉換對應beanName 傳入的參數name不必定就是beanName, 多是別名, 也多是FactoryBean, 因此須要一系列的解析, 這些解析內容包括以下內容: 1. 去除FactoryBean的修飾符, 也就是若是name="$aa", 那麼會首先去除&而使name="aa". 2. 取指定alias所表示的最終beanName, 例如別名A指向名稱爲B的bean則返回B;若別名A只想別名B, 別名B又指向名稱爲C的bean則返回C. */
		final String beanName = transformedBeanName(name);
		Object bean;

		/* (二). 嘗試從緩存中加載單例. 單例在Spring的同一個容器內只會被建立一次, 後續再獲取bean, 就直接從單例緩存中獲取了. 固然這裏也只是嘗試加載, 首先嚐試從緩存中加載, 若是加載不成功則再次嘗試從singleFactories中加載, 由於再建立單例bean的時候會存在依賴注入的狀況,而在建立依賴的時候爲了不循環依賴,再Spring中建立bean的原則是不等bean建立完成就會將建立bean的ObjectFactory提前曝光加入到緩存中, 一旦下一個bean建立時候須要依賴上一個bean則直接使用ObjectFactory */
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
      /* (三). bean的實例化 若是從緩存中獲得了bean的原始狀態, 則須要對bean進行實例化.緩存中記錄的只是最原始的bean狀態, 並不必定是咱們最終想要的bean. 舉個例子嗎加入咱們須要對工廠bean進行處理, 那麼這裏獲得的實際上是工廠bean的初始狀態, 可是咱們真正須要的是工廠bean中定義的factory-method方法中返回的bean, 而getObjectForBeanInstance就是完成這個工做的. */
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
      /* (四). 原型模式的依賴檢查 只有在單例狀況下才會嘗試解決循環依賴, 原型模式狀況下, 若是存在A中又B的屬性, B中有A的屬性, 那麼當依賴注入的時候, 就會產生當A還未建立完的時候由於對於B的建立再次返回建立A, 形成循環依賴. 也就是isPrototypeCurrentlyInCreation(beanName)判斷true */
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			/* (五). 檢查parentBeanFactory 從代碼上看, 若是緩存沒有數據的話直接轉到父類工廠上去加載了, 這是爲何呢? 可能讀者忽略了一個很重要的判斷條件: parentBeanFactory != null && !containsBeanDefinition(beanName). parentBeanFactory != null. parentBeanFactory若是爲空, 則其餘一切都是浮雲, 這個沒什麼說的, 可是!containsBeanDefinition(beanName)就比較重要了, 它是在檢測若是當前加載的XML配置文件中不包含beanName所對應的配置, 就只能到parentBeanFactory去嘗試下了, 而後遞歸的調用getBean方法. */
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
        /* (六). 將存儲XML配置文件的GernericBeanDefinition轉換爲RootBeanDefinition. 由於從XML配置文件中讀取到的Bean信息是存儲在GernericBeanDefinition中的, 可是全部的Bean的後續處理都是針對於RootBeanDefinition的, 因此這裏須要進行一個轉換, 轉換的同時若是父類bean不爲空的話, 則會一併合併父類的屬性. */
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				/* (七). 尋找依賴 由於bean的初始化過程極可能會用到某些屬性, 而某些屬性極可能是動態配置的, 而且配置成依賴與其餘的bean, 那麼這個時候就有必要先加載依賴的bean, 因此, 在Spring的加載順序中, 在初始化某一個bean的時候首先會初始化這個bean所對應的依賴. */
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				/* (八). 針對不一樣的scope進行bean的建立 咱們都知道, 在Spring中存在不一樣的scope, 其中默認的是singleton, 可是還有其餘的配置諸如prototype, request之類的. 在這個步驟中, Spring會根據不一樣的配置進行不一樣的初始化策略. */
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					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 name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							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;
			}
		}

		/* (九). 類型轉換 程序到這裏返回bean後基本結束了, 一般對該方法的調用參數requiredType是爲空的, 可是可能會存在這樣的狀況, 返回的bean實際上是個String, 可是requiredType卻傳入Integer類型, 那麼這時候本步驟就會起做用了, 它的功能是將返回的bean轉換爲requiredType所指定的類型.固然, String轉換爲Integer是最簡單的一種轉換, 在Spring中提供了各類各樣的轉換器, 用戶也能夠本身擴輾轉換器來知足需求. 通過上面的步驟後bean的加載就結束了, 這個時候就能夠返回咱們所須要的bean了, 其中最重要的步驟8, 針對不一樣的scope進行bean的建立, 你會看到各類經常使用的Spring特性在這裏的實現. */
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

複製代碼

5.1 FactoryBean的使用

通常狀況下, Spring經過反射機制利用bean的class屬性指定實現類來實例化bean. 在某些狀況下, 實例化bean過程比較複雜, 若是按照傳統的方式, 則須要在<bean>中提供大量的配置信息, 配置方式的靈活性是受限的, 這是採用編碼的方式可能會獲得一個簡單的方案. Spring爲此提供了一個 org.springframework.bean.factory.FactoryBean 的工廠類接口, 用戶能夠經過實現該接口定製實例化bean的邏輯.

FactoryBean接口對於Spring框架來講佔有重要的地位, Spring自己就提供了70多個FactoryBean的實現. 它們隱藏了實例化一些複雜bean的細節, 給上層應用帶來了便利. 從Spring3.0開始, FactoryBean開始支持泛型, 即接口聲明改成FactoryBean<T>的形式:
複製代碼
public interface FactoryBean<T> {
    T getObject() throws Exception;
    Class<?> getObjectType();
    default boolean isSingleton() {
      return true;
    }
  }
複製代碼

在該接口中還定義了3個方法:git

  • T getObject() : 返回由FactoryBean建立的bean的實例. 若是 isSingleton() 返回true, 則該實例會放到Spring容器中單實例緩存池中.
  • boolean isSingleton() : 返回由FactoryBean建立的bean的實例的做用域是singletion仍是prototype.
  • Class<?> getObjectType() : 返回FactoryBean建立的bean的類型.

當配置文件中的class屬性配置的實現類是FactoryBean時, 經過getBean()方法返回的不是FactoryBean自己, 而是FactoryBean#getObject()方法所返回的對象, 至關於FactoryBean#getObject()代理了getBean()方法.spring

5.2 緩存中獲取單例Bean

介紹過FactoryBean的用法後, 咱們就能夠了解bean加載的過程了. 前面已經提到過, 單例在Spring的同一個容器內只會被建立一次, 後續再獲取bena直接從單例緩存中獲取, 固然這裏也是隻嘗試加載, 首先嚐試從緩存中加載, 而後再次嘗試從singletonFactories中加載. 由於再建立單例bean的時候會存在依賴注入的狀況, 而在建立依賴的時候爲了不循環依賴, Spring建立bean的原則是不等bean建立完成就會將查u你感受愛你bean的ObjectFactory提前曝光加到緩存中, 一旦下一個bean建立時須要依賴上個bean, 則直接使用ObjectFactory.
複製代碼
@Override
	public Object getSingleton(String beanName) {
    // 參數true設置標識容許早起依賴
		return getSingleton(beanName, true);
	}

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 檢查緩存中是否存在實例
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      // 若是爲空, 則鎖定全局變量並進行處理
			synchronized (this.singletonObjects) {
        // 若是此bean正在加載則不處理
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
          // 當某些方法須要提早初始化的時候則會調用addSingletonFactory方法將對應的ObjectFactory初始化策略存儲在singletonFactories
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
            // 調用預先設定的getObject方法
						singletonObject = singletonFactory.getObject();
            // 記錄再緩存中, earlySingletonObjects和singletonFactories互斥
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}
複製代碼

這個方法由於涉及循環依賴的檢測, 以及涉及不少變量的記錄存取, 因此讓不少讀者摸不着頭腦. 這個方法首先嚐試從singletonObjects裏面獲取實例, 若是獲取不到, 在嘗試從singletonFactories裏面獲取beanName對應的ObjectFactory, 而後調用這個ObjectFactory的getObject來建立bean, 並放到earlySingletonObjects裏面去, 而且從singletonFactories裏面remove掉這個ObjectFactory, 而對於後續的全部內存操做都只爲了循環依賴檢測時候使用, 也就是在allowEarlyReference爲true的狀況下才會使用.數組

這裏涉及用戶存儲bean的不一樣mao, 簡單解釋以下.緩存

  • singletonObjects: 用戶保存BeanName和建立bean實例之間的關係, bean name —> bean instance.
  • singletonFactoriesL用於保存BeanName和建立bean的工廠之間的關係, bean name —> ObjectFactory.
  • earlySingletonObjects: 也是保存BeanName 和建立bean實例之間的關係, 與singletonObjects不一樣之處在於, 當一個單例bean被放到這裏面後, 那麼當bean還在建立過程當中, 就能夠經過getBean方法獲取到了, 其目的是用來檢測循環引用.
  • registeredSingletons: 用來保存當前全部已註冊的bean.

5.3 從bean的實例中獲取對象

在getBean方法中, getObejctForBeanInstance是個高頻率使用的方法, 不管是從緩存中得到bean仍是根據不一樣的scope策略加載bean. 總之, 咱們獲得bean的實例後要作的第一步就是調用這個方法來檢測一下正確性, 其實就是用於檢測當前bean是不是FactoryBean類型的bean, 若是是, 那麼須要調用該bean對應的FactoryBean實例中的getObject()做爲返回值.

不管是從緩存中獲取到的bean仍是經過不一樣的scope策略加載的bean都只是最原始的bean狀態, 並不必定是咱們最終想要的bean. 舉個例子, 加入咱們須要對工廠bean進行處理, 那麼這裏獲得的實際上是工廠bean的初始狀態, 可是咱們真正須要的是工廠bean中定義的factory-method方法中返回的bean, 而getObjectForBeanInstance方法就是完成這個工做的.
複製代碼

org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstancebash

protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// 若是指定的name是工廠相關(以&爲前綴)且beanInstance又不是FactoryBean類型則驗證不經過
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
			}
		}

		// 如今咱們有了個bean的實例, 這個實例可能會是正常的bean或者是FactoryBean
    // 若是是FactoryBean咱們使用它建立實例, 可是若是用戶想要直接獲取工廠實例而不是工廠的getObject方法對應的實例那麼傳入的name應該加入前綴&
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

    // 加載FactoryBean
		Object object = null;
		if (mbd == null) {
      // 嘗試從緩存中加載bean
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// 到這裏已經明確知道beanInstance必定是FactoryBean類型
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// containsBeanDefinition檢測beanDefinitionMap中也就是在全部已經加載的類中檢測是否認義beanName
			if (mbd == null && containsBeanDefinition(beanName)) {
        // 將存儲再XML配置文件的GenericBeanDefinition轉換爲RootBeanDefinition, 若是指定BeanName是子Bean的話同時會合並父類的相關屬性
				mbd = getMergedLocalBeanDefinition(beanName);
			}
      // 是不是用戶定義的而不是應用程序自己定義的
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}
複製代碼

從上面代碼來看, 其實這個方法並無什麼重要的信息, 大可能是些輔助代碼以及一些功能性的判斷, 而真正的核心代碼卻委託給了getObjectFromFactoryBean, 咱們來看看getObjectFromBeanInstance中所作的工做.架構

  1. 對FactoryBean正確性的驗證
  2. 對非FactoryBean不作任何處理
  3. 對bean進行轉換
  4. 將從Factory中解析bean的工做委託給getObjectFromFactoryBean.

org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBeanapp

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							beforeSingletonCreation(beanName);
							try {
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
          // 調用ObjectFactory的後置處理器
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}


	private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) throws BeanCreationException {

		Object object;
		try {
      // 須要權限驗證
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
        // 直接調用getObject方法
				object = factory.getObject();
			}
		}
		catch (FactoryBeanNotInitializedException ex) {
			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
		}

		// Do not accept a null value for a FactoryBean that's not fully
		// initialized yet: Many FactoryBeans just return null then.
		if (object == null) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			object = new NullBean();
		}
		return object;
	}

複製代碼

5.4 獲取單例

若是緩存中不存在已經加載的單例bean就須要從頭開始bean的加載過程了, 而Spring中使用了getSingleton的重載方法實現bean的加載過程.框架

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)less

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "'beanName' must not be null");
    // 全局變量須要同步
		synchronized (this.singletonObjects) {
      // 首先檢查對應的bean是否已經加載過, 由於singleton模式其實就是複用以建立的bean, 因此這一步時必須的
			Object singletonObject = this.singletonObjects.get(beanName);
      // 若是爲空才能夠進行singleton的初始化
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
        // 記錄加載狀態, 也就是經過this.singletonsCurrentlyInCreation.add(beanName)將當前正要建立的bean記錄在緩存中, 這樣即可以對循環依賴進行檢測.
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<Exception>();
				}
				try {
          // 初始化bean
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
          // 
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
          // 加入緩存
					addSingleton(beanName, singletonObject);
				}
			}
			return (singletonObject != NULL_OBJECT ? singletonObject : null);
		}
	}

複製代碼

上述代碼中實際上是使用了回調方法, 使得程序能夠在單例建立的先後作一些準備及處理操做, 而真正的獲取單例的bean的方法其實並非在此方法中實現的, 其實現邏輯是在ObjectFactory類型的實例singletonFactory中實現的. 而這些準備及處理操做包括以下內容:

  1. 檢查緩存是否已經加載過
  2. 若沒有加載, 則記錄beanName的正在加載狀態
  3. 加載單例前記錄加載狀態

可能你會以爲beforeSingletonCreation方法是個空實現, 裏面沒有任何邏輯, 但其實不是. 這個函數中作了一個很重要的操做: 記錄加載狀態, 也就是經過this.singletonsCurrentlyInCreation.add(beanName)將當前正要建立的bean記錄在緩存中, 這樣即可以對循環依賴進行檢測.

protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

複製代碼
  1. 經過調用參數傳入的ObjectFactory的個體Object方法實例化bean.
  2. 加載單例後的處理方法調用.

同步驟(3)的記錄加載狀態類似, 當bean加載結束後須要移除緩存中對該bean的正在加載狀態的記錄.

protected void afterSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
		}
	}

複製代碼
  1. 將結果記錄至緩存並刪除加載bean過程當中所記錄的各類輔助狀態.

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingleton

protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

複製代碼
  1. 返回處理結果

雖然咱們已經從外部瞭解了加載bean的邏輯架構, 但如今咱們尚未開始對bean加載功能的探索, 以前提到過, bena的加載邏輯實際上是在傳入的ObjectFactory類型的參數singletonFatory中定義的, 咱們反推參數的獲取, 獲得以下代碼

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								// Explicitly remove instance from singleton cache: It might have been put there
								// eagerly by the creation process, to allow for circular reference resolution.
								// Also remove any beans that received a temporary reference to the bean.
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

複製代碼

ObjectFactory的核心部分其實只是調用了createBean的方法, 因此還須要到createBean方法中尋找.

5.5 準備建立Bean

咱們不可能期望在一個函數中完成一個複雜的邏輯, 並且咱們跟蹤了這麼多Spring代碼, 經歷了這麼多函數, 或多或少也發現了一些規律: 一個真正幹活的函數實際上是以do開頭的, 好比doGetObjectFromFactoryBean; 而給咱們錯覺的函數getObjectFromFactoryBean, 其實只是從全局角度去作些統籌的工做. 這個規則對於createBean也不例外, 那麼咱們看看在createBean函數中作了那些準備工做.

org.springframework.beans.factory.support.AbstractBeanFactory#createBean

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])

@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
    // 鎖定class, 根據設置的class屬性或者根據className來解析Class
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
    // 驗證及準備覆蓋的方法
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      // 給BeanPostProcessors一個機會來返回代理來替代真正的實例
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}


複製代碼

從代碼中咱們能夠總結出函數完成的具體步驟及功能.

  1. 根據設置的class屬性或者根據className來解析Class.
  2. 對override屬性進行標記及驗證.

不少讀者可能會不知道這個方法的做用, 由於再Spring的配置裏面根本就沒有諸如override-method之類的配置, 那麼這個方法究竟是幹什麼用的呢?

其實在Spring中確實沒有override-method這樣的配置, 可是若是讀過前面的部分, 可能會有所發現, 在Spring配置中存在lookup-method和replace-method的, 而這兩個配置的加載其實就是將配置統一存放在BeanDefinition中methodOverrides屬性裏, 而這個函數的操做其實也就是針對於這兩個配置的.

  1. 應用初始化前的後處理器, 解析指定bean是否存在初始化前的短路操做.
  2. 建立bean.

咱們首先查看下對override屬性標記及驗證的邏輯實現.

5.5.1 處理 override 屬性

查看源碼中 AbstractBeanDefinition 類的 prepareMethodOverrides 方法:

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
		// Check that lookup methods exists.
		MethodOverrides methodOverrides = getMethodOverrides();
		if (!methodOverrides.isEmpty()) {
			Set<MethodOverride> overrides = methodOverrides.getOverrides();
			synchronized (overrides) {
				for (MethodOverride mo : overrides) {
					prepareMethodOverride(mo);
				}
			}
		}
	}

	protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
		int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
		if (count == 0) {
			throw new BeanDefinitionValidationException(
					"Invalid method override: no method with name '" + mo.getMethodName() +
					"' on class [" + getBeanClassName() + "]");
		}
		else if (count == 1) {
			// Mark override as not overloaded, to avoid the overhead of arg type checking.
			mo.setOverloaded(false);
		}
	}

複製代碼

以前反覆提到過, 在Spring配置中存在 lookup-method 和 replace-method 兩個配置功能, 而這兩個配置的加載其實就是將配置統一存放在 BeanDefinition 中的 methodOverrides 屬性裏, 這兩個功能實現原理實際上是在 bean 實例化的時候若是檢測到存在 methodOverrides 屬性, 會動態地爲當前 bean 生成代理並使用對應的攔截器爲 bean 作加強處理, 相關邏輯實如今 bean 的實例化部分詳細介紹.

對於方法的匹配來說, 若是一個類總存在若干個重載方法, 那麼在函數調用及加強的時候還須要根據參數類型進行匹配, 來最終確認當前調用的究竟是哪一個函數. 可是Spring將一部分匹配工做在這裏完成了, 若是當前類中的方法只有一個, 那麼就設置該方法沒有被重載, 這樣在後續調用的時候就能夠直接使用找到的方法, 而不須要進行方法的參數匹配驗證了, 並且還能夠提早對方法存在性進行驗證.

5.5.2 實例化的前置處理

在真正調用 doCreate 方法建立 bean 的實例前使用了這樣一個方法 resolveBeforeInstantiation(beanName, mdb) 對 BeanDefinigiton 中的屬性作些前置處理. 固然, 不管其中是否有相應的邏輯實現咱們均可以理解, 由於真正邏輯實現先後留有處理函數也是可擴展的一種提現, 可是, 這並非最重要的, 在函數中還提供了一個短路判斷, 這纔是最爲關鍵的部分.

if (bean != null) {
  return bean;
}

複製代碼

當通過前置處理後返回的結果若是不爲空, 那麼會直接略事後續的 Bean 的建立而直接返回結果. 這一特性雖然很容易被忽略, 可是卻起着相當重要的做用, 咱們熟知的AOP功能就是基於這裏的判斷的.

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// 若是還沒有被解析
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

複製代碼

此方法中最吸引咱們的無疑是兩個方法 applyBeanPostProcessorsBeforeInstantiation 以及 applyBeanPostProcessorsAfterInitialization . 兩個方法實現的很是簡單, 無非是對後處理器中的全部 InstantiationAwareBeanPostProcessor 類型的後處理器進行 postProcessAfterInstantiation 方法和 BeanPostProcessor 的 postProcessAfterInitialization 方法的調用.

  1. 實例化前的後處理器應用

bean的實例化前調用, 也就是將 AbstractBeanDefinition 轉換爲 BeanWrapper 前的處理. 給子類一個修改 BeanDefinition 的機會, 也就是說當程序通過這個方法後, bean可能已經不是咱們認爲的 bean 了, 而是或許成爲了一個通過處理的代理 bean, 多是經過 cglib 生成的, 也多是經過其餘技術生成的,

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

複製代碼
  1. 實例化後的後處理器應用

在講解從緩存中獲取單例 bean 的時候就提到過, Spring 中的規則是在 bean 的初始化後儘量保證將註冊的後處理器的 postProcessAfterInstantiation 方法應用到該 bean 中, 由於若是返回的 bean 不爲空, 那麼便不會再次經理普通bean的建立過程, 因此只能在這裏應用後處理器的 postProcessAfterInstantiation 方法.

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			result = beanProcessor.postProcessAfterInitialization(result, beanName);
			if (result == null) {
				return result;
			}
		}
		return result;
	}

複製代碼

5.6 循環依賴

實例化bean是一個很是複雜的過程, 而其中最比較難以理解的就是對循環依賴的解決.

5.6.1 什麼是循環依賴

循環依賴就是循環引用, 就是兩個或多個 bean 相互之間持有對方, 好比 CircleA 引用 CricleB, CircleB 引用 CircleC, CricleC引用 CircleA, 則它們最終反應爲一個環. 此處不是循環調用, 循環調用是方法之間的循環調用.

循環調用是沒法解決的, 除非有終結條件, 不然就是死循環, 最終致使內存溢出錯誤.

5.6.2 Spring 如何解決循環依賴

Spring 容器循環依賴包括構造器循環依賴和setter循環依賴, 那Spring容器如何解決循環依賴呢?

在Spring中將循環依賴處理分紅了3中狀況.

  1. 構造器循環依賴

表示經過構造器注入構成的循環依賴, 此依賴時沒法解決的, 只能拋出 BeanCurrentlyInCreationException 異常表示循環依賴.

如在建立 TestA 類時, 構造器須要 TestB 類, 那將去建立 TestB, 在建立 TestB 類時又發現須要 TestC 類, 則又去建立 TestC, 最終在建立 TestC 時發現有須要 TestA, 從而造成了一個環, 沒辦法建立.

Spring 容器將每個正在建立的 bean 標識符放在一個 "當前建立bean池" 中, bean 標識符在建立過程當中將一直保持在這個池中, 所以若是在建立 bean 過程當中發現本身已經在 "當前建立bean池" 裏時, 將拋出 BeanCurrentlyInCreationException異常表示循環依賴; 而對於建立完畢的 bean 將從 "當前建立bean池" 裏清楚掉.

  1. setter 循環依賴

表示經過setter注入方式構成循環依賴. 對於setter 注入形成的依賴是經過 Spring 容器提早暴露剛完成構造器注入但未完成其餘步驟(如 setter 注入)的 bean 來完成的, 並且只能解決單例做用域的 bean 循環依賴. 經過提早暴露一個單例工廠方法, 從而使其餘 bean 能引用到該 bean, 以下代碼所示:

addSingletonFactory(beanName, new ObjectFactory() {
  public Object getObject() throws BeanException {
    return getEarlyBeanReference(beanName, mbd, bean);
  }
});

複製代碼

​ 具體步驟以下.

​ (1). Spring 容器建立單例 "testA" bean, 首先根據無參構造器建立bean, 並暴露一個 "ObjectFactory" 用於返回一個提起暴露一個建立中的 bean, 並將 "testA" 標識符放到 "當前建立bena池" , 而後進行 setter 注入 "testB".

​ (2). Spring 容器建立單例 "testB" bean, 首先根據無參構造器建立bean, 並暴露一個 "ObjectFactory" 用於返回一個提起暴露一個建立中的 bean, 並將 "testB" 標識符放到 "當前建立bena池" , 而後進行 setter 注入 "testC".

​ (3). Spring 容器建立單例 "testC" bean, 首先根據無參構造器建立bean, 並暴露一個 "ObjectFactory" 用於返回一個提起暴露一個建立中的 bean, 並將 "testC" 標識符放到 "當前建立bena池" , 而後進行 setter 注入 "circle". 進行注入 "testA" 時因爲提早暴露了 "ObjectFactory" 工廠, 從而使用它返回提早暴露一個建立中的 bean.

​ (4). 最後在依賴注入 "testB" 和 "testA", 完成 setter 注入

  1. prototype範圍的依賴處理

對於 "prototype" 做用域 bean, Spring 容器沒法完成依賴注入, 由於Spring 容器不進行緩存 "prototype" 做用域的 bean, 所以沒法提早暴露一個建立中的 bean.

對於 "singleton" 做用域 bean, 能夠經過 "setAllowCircularReferences(false)"; 來禁用循環引用.

5.7 建立 bean

介紹了循環依賴以及Spring中循環依賴的處理方式後, 繼續4,5小節的內容. 當經歷過 resolveBeforeInstantiation 方法後, 程序有兩個選擇, 若是建立了代理或者說重寫了 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法並在方法 postProcessBeforeInstantiation 中改變了 bean, 則直接返回就能夠了, 不然須要進行常規 bean 的建立. 而這常規 bean 的建立就是在 doCreateBean 中完成的.

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

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

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
      // 根據指定 bean 使用對應的策略建立新的實例, 如: 工廠方法, 構造函數自動注入, 簡單初始化
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
		mbd.resolvedTargetType = beanType;

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
          // 應用 MergedBeanDefinitionPostProcessor
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
    /* 是否須要提前曝光: 單例&容許循環依賴&當前bean正在建立中, 檢測循環依賴 */
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
      // 爲避免後期循環依賴, 能夠在bean初始化完成前將建立實例的ObjectFactory加入工廠
			addSingletonFactory(beanName, new ObjectFactory<Object>() {
				@Override
				public Object getObject() throws BeansException {
          // 對 bean 再一次依賴引用, 主要應用 SmartInstantiationAware BeanPostProcessor, 其中咱們熟悉的AOP就是在這裏將advice動態織入bean中, 若沒有則直接返回bean, 不作任何處理
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
      // 對bean進行填充, 將各個屬性值注入, 其中可能存在依賴於其餘bean的屬性, 則會遞歸初始依賴bean
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
       // 調用初始化方法, 好比init-method
				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);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
      // earlySingletonReference只有在檢測到有循環依賴的狀況下才會不爲空
			if (earlySingletonReference != null) {
        // 若是exposedObject 沒有在初始化方法中被改變, 也就是沒有被加強
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
            // 檢測依賴 
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
          /* 由於bean建立後其所依賴的bean必定是已經建立的, actualDependentBeans不爲空則表示當前bean建立後其依賴的bean卻沒有沒所有建立完, 也就會說存在循環依賴 */
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
      // 根據scope註冊bean
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

複製代碼

儘管日誌與異常的內容很是重要, 可是在閱讀源碼的時候彷佛大部分人都會直接忽略掉. 在此不深刻探討日誌及異常的設計, 咱們看看整個函數的概要思路.

  1. 若是是單例則須要首先清除緩存.
  2. 實例化bean, 將 BeanDefinition 轉換爲 BeanWrapper.

轉換是一個複雜的過程, 可是咱們能夠嘗試歸納大體的功能, 以下所示.

  • 若是存在工廠方法則使用工廠方法進行初始化
  • 一個類有多個構造函數, 每一個構造函數都有不一樣的參數, 因此須要根據參數鎖定構造函數並進行初始化.
  • 若是既不存在工廠方法也不存在帶有參數的構造函數, 則使用默認的構造函數進行bean的實例化.
  1. MergedBeanDefinitionPostProcessor 的應用.

bean 合併後的處理, Autowired註解正式經過此方法實現注入類型的預解析.

  1. 依賴處理

在Spring 中會有循環依賴的狀況, 例如, 當A中含有B的屬性, 而B中又含有A的屬性時就會構成一個循環依賴, 此時若是A和B都是單例, 那麼在Spring中處理方式就是當建立B的時候, 實際自動注入A的步驟時, 並非直接去再次建立A, 而是經過放入緩存中的ObjectFactory來建立實例, 這樣就解決了循環依賴的問題.

  1. 屬性填充. 將全部屬性填充至bean的實例中.
  2. 循環依賴檢查

以前有提到過, 在Spring 中解決循環依賴只對單例有效, 而對於prototype的bean, Spring沒有好的解決辦法, 惟一要作的就是拋出異常. 在這個步驟裏面會檢測已經加載的bean是否已經出現了循環依賴, 並判斷是否須要拋出異常/

  1. 註冊DisposableBean

若是配置了destroy-method, 這裏須要註冊以便於在銷燬時候調用.

  1. 完成建立並返回.

能夠看到上面的步驟很是的繁瑣, 每一步驟都使用了大量的代碼來完成其功能, 最複雜也是最難以理解的當屬循環依賴的處理, 在真正進入doCreateBean前咱們有必要先了解循環依賴.

5.7.1 建立Bean的實例

當咱們瞭解了循環以來之後就能夠深刻分析建立bean的每一個步驟了, 首先咱們從createBeanInstance開始,

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
		// Make sure bean class is actually resolved at this point.
    // 解析class
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		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);
		}

		// Shortcut when re-creating the same bean...
		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);
			}
		}

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

		// No special handling: simply use no-arg constructor.
    // 使用默認構造函數
		return instantiateBean(beanName, mbd);
	}

複製代碼

雖然代碼中實例化的細節很是複雜, 可是在 createBeanIntance 方法中咱們仍是能夠清晰的看到實例化的邏輯的.

  1. 若是在 RootBeanDefinition 中存在 factoryMethodName屬性, 或者說在配置文件配置了 factory-method, 那麼Spring 會嘗試使用 instantiateUsingFactoryMethod(beanName, mbd, args) 方法根據 RootBeanDefinition 中的配置生成 bean 的實例.

  2. 解析構造函數並進行構造函數的實例化. 由於一個bean對應的類中可能會有多個構造函數, 而每一個構造函數的參數不一樣, Spring 在根據參數及類型去判斷最終會使用哪一個構造函數進行實例化. 可是判斷的過程是個比較消耗性能的步驟, 因此採用緩存機制, 若是已經解析過則不須要重複解析而是直接從RootBeanDefinition 中的屬性resolvedConstructorOrFactoryMethod 緩存的值去取, 不然須要再次解析, 並將解析的結果添加至 RootBeanDefinition 中的屬性 resolvedConstructorOrFactoryMethod 中.

    • autowireConstructor

      對於實例的建立 Spring 中分紅了兩種狀況, 一種是通用的實例化, 另外一種是帶有參數的實例化. 帶有參數的實例化過程至關複雜, 由於存在着不肯定性, 因此在判斷對應參數上作了大量工做.

      org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor

    protected BeanWrapper autowireConstructor( String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) {
      		return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
      	}
    
    public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd, Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
    
    BeanWrapperImpl bw = new BeanWrapperImpl();
    this.beanFactory.initBeanWrapper(bw);
    
    Constructor<?> constructorToUse = null;
    ArgumentsHolder argsHolderToUse = null;
    Object[] argsToUse = null;
    
      // explicitArgs 經過getBean方法傳入
      // 若是getBean方法調用的時候指定方法參數那麼直接使用
    if (explicitArgs != null) {
    	argsToUse = explicitArgs;
    }
    else {
    // 若是getBean方法調用的時候沒有指定方法參數則嘗試從配置文件中解析
    	Object[] argsToResolve = null;
    // 嘗試從緩存中獲取
    	synchronized (mbd.constructorArgumentLock) {
    		constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
    		if (constructorToUse != null && mbd.constructorArgumentsResolved) {
        // 從緩存中獲取
    			argsToUse = mbd.resolvedConstructorArguments;
    			if (argsToUse == null) {
          // 配置的構造函數參數
    				argsToResolve = mbd.preparedConstructorArguments;
    			}
    		}
    	}
    // 若是緩存中存在
    	if (argsToResolve != null) {
      // 解析參數類型, 如給定方法的構造函數A(int, int) 則經過此方法後就會把配置中("1", "1")轉換爲 (1, 1)
      // 緩存中的值多是原始值也多是最終值
    		argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
    	}
    }
    
      // 沒有被緩存
    if (constructorToUse == null) {
    	// Need to resolve the constructor.
    	boolean autowiring = (chosenCtors != null ||
    			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
    	ConstructorArgumentValues resolvedValues = null;
    
    	int minNrOfArgs;
    	if (explicitArgs != null) {
    		minNrOfArgs = explicitArgs.length;
    	}
    	else {
      // 提取配置文件中的配置的構造函數參數
    		ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
      // 用於承載解析後的構造函數參數的值
    		resolvedValues = new ConstructorArgumentValues();
      // 能解析到的參數個數
    		minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
    	}
    
    	// Take specified constructors, if any.
    	Constructor<?>[] candidates = chosenCtors;
    	if (candidates == null) {
    		Class<?> beanClass = mbd.getBeanClass();
    		try {
    			candidates = (mbd.isNonPublicAccessAllowed() ?
    					beanClass.getDeclaredConstructors() : beanClass.getConstructors());
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    					"Resolution of declared constructors on bean Class [" + beanClass.getName() +
    					"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
    		}
    	}
    
    // 排序給定的構造函數, public構造函數優先參數數量降序, 非public構造函數參數數量降序
    	AutowireUtils.sortConstructors(candidates);
    	int minTypeDiffWeight = Integer.MAX_VALUE;
    	Set<Constructor<?>> ambiguousConstructors = null;
    	LinkedList<UnsatisfiedDependencyException> causes = null;
    
    	for (Constructor<?> candidate : candidates) {
    		Class<?>[] paramTypes = candidate.getParameterTypes();
    
      // 若是已經找到選用的構造函數或者須要的參數個數小於當前的構造函數參數個數則終止, 由於已經按照參數個數降序排列
    		if (constructorToUse != null && argsToUse.length > paramTypes.length) {
    			// Already found greedy constructor that can be satisfied ->
    			// do not look any further, there are only less greedy constructors left.
    			break;
    		}
    		if (paramTypes.length < minNrOfArgs) {
        // 參數個數不相等
    			continue;
    		}
    
    		ArgumentsHolder argsHolder;
    		if (resolvedValues != null) {
        // 有參數則根據值構造對應參數類型的參數
    			try {
          // 註釋上獲取參數名稱
    				String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
    				if (paramNames == null) {
            // 獲取參數名稱探索器
    					ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
    					if (pnd != null) {
              // 獲取指定構造函數的參數名稱
    						paramNames = pnd.getParameterNames(candidate);
    					}
    				}
          // 根據名稱和數據類型建立參數持有者
    				argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
    						getUserDeclaredConstructor(candidate), autowiring);
    			}
    			catch (UnsatisfiedDependencyException ex) {
    				if (this.beanFactory.logger.isTraceEnabled()) {
    					this.beanFactory.logger.trace(
    							"Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
    				}
    				// Swallow and try next constructor.
    				if (causes == null) {
    					causes = new LinkedList<UnsatisfiedDependencyException>();
    				}
    				causes.add(ex);
    				continue;
    			}
    		}
    		else {
    			// Explicit arguments given -> arguments length must match exactly.
    			if (paramTypes.length != explicitArgs.length) {
    				continue;
    			}
        // 構造函數沒有參數的狀況
    			argsHolder = new ArgumentsHolder(explicitArgs);
    		}
    
      // 探測是否有不肯定性的構造函數存在, 例如不一樣構造函數的參數爲父子關係
    		int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
    				argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
    		// Choose this constructor if it represents the closest match.
      // 若是它表明着當前最接近的匹配則選擇做爲構造函數
    		if (typeDiffWeight < minTypeDiffWeight) {
    			constructorToUse = candidate;
    			argsHolderToUse = argsHolder;
    			argsToUse = argsHolder.arguments;
    			minTypeDiffWeight = typeDiffWeight;
    			ambiguousConstructors = null;
    		}
    		else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
    			if (ambiguousConstructors == null) {
    				ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
    				ambiguousConstructors.add(constructorToUse);
    			}
    			ambiguousConstructors.add(candidate);
    		}
    	}
    
    	if (constructorToUse == null) {
    		if (causes != null) {
    			UnsatisfiedDependencyException ex = causes.removeLast();
    			for (Exception cause : causes) {
    				this.beanFactory.onSuppressedException(cause);
    			}
    			throw ex;
    		}
    		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    				"Could not resolve matching constructor " +
    				"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
    	}
    	else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
    		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    				"Ambiguous constructor matches found in bean '" + beanName + "' " +
    				"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
    				ambiguousConstructors);
    	}
    
    	if (explicitArgs == null) {
      // 將解析的構造函數加入緩存
    		argsHolderToUse.storeCache(mbd, constructorToUse);
    	}
    }
    
    try {
    	Object beanInstance;
    
    	if (System.getSecurityManager() != null) {
    		final Constructor<?> ctorToUse = constructorToUse;
    		final Object[] argumentsToUse = argsToUse;
    		beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
    			@Override
    			public Object run() {
    				return beanFactory.getInstantiationStrategy().instantiate(
    						mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
    			}
    		}, beanFactory.getAccessControlContext());
    	}
    	else {
    		beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
    				mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
    	}
    
    // 將構建的實例加入BeanWrapper中
      			bw.setBeanInstance(beanInstance);
      			return bw;
      		}
      		catch (Throwable ex) {
      			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
      					"Bean instantiation via constructor failed", ex);
      		}
      	}
    
    複製代碼
    邏輯很複雜, 函數代碼量很大, 咱們總覽一下整個函數, 其實現的功能考慮了一下幾個方面.
    
    1. 構造函數參數的肯定.
    
       - 根據 explicitArgs 參數判斷
    
         若是傳入的參數 explicitArgs 不爲空, 那麼能夠直接肯定參數, 由於 explicitArgs 參數是在調用 Bean 的時候用戶指定的, 在 BeanFactory 類中存在這樣的方法:
    
         ```java
         Object getBean(String name, Object ... args) throws BeansException;
         ```
    
         在獲取 bean 的時候, 用戶不但能夠指定 bean 的名稱還能夠指定 bean 所對應類的構造函數或者工廠方法的方法參數, 主要用於靜態工廠方法的調用, 而這裏是須要給定徹底匹配的參數的, 因此, 即可以判斷, 若是傳入參數 explicitArgs 不爲空, 則能夠肯定構造函數參數就是它.
    
       - 緩存中獲取
    
         除此以外, 肯定參數的辦法若是以前已經分析過, 也就是說構造函數參數已經記錄在緩存中, 那麼即可以直接拿來使用. 並且, 這裏要提到的是, 在緩存中緩存的多是參數的最終類型也多是參數的初始類型, 例如: 構造函數參數要求的是int類型, 可是原始的參數值多是String 類型的 "1", 那麼即便在緩存中獲得了參數, 也須要通過類型轉換器的過濾以確保參數類型與對應的構造函數參數類型徹底對應.
    
       - 配置文件中獲取
    
         若是不能根據傳入的參數 explicitArgs 肯定構造函數的參數也沒法在緩存中達到相關信息, 那麼只能開始新一輪的分析了.
    
         分析從獲取配置文件中配置的構造函數信息開始, 通過以前的分析, 咱們知道, Spring中配置文件中的信息通過轉化都會經過 BeanDefinition 實例承載, 也就是參數 mbd 中包含, 那麼能夠經過調用 mbd.getConstructorArgumentValues() 參數獲取配置的構造函數信息. 有了配置中的信息即可以獲取對應的參數值信息了, 獲取參數值的信息包括直接指定值, 如: 直接指定構造函數中某個值爲原始類型 String 類型, 或者是一個對其餘 bean 的引用, 而這一處理委託給 resolveConstructorArguments 方法, 並返回能解析到的參數的個數.
    
    2. 構造函數的肯定
    
       通過了第一步後已經肯定了構造函數的參數, 接下來的任務就是根據構造函數參數在全部構造函數中鎖定對應的構造函數, 而匹配的方法就是根據參數個數匹配, 因此在匹配以前須要先對構造函數按照 public 構造函數優先參數數量降序, 非public構造函數參數數量降序. 這樣能夠在便利的狀況下迅速判斷排在後面的構造函數參數個數是否符合條件.
    
       因爲在配置文件中並非惟一限制使用參數位置索引的方式去建立, 一樣還支持指定參數名稱進行設定參數值的狀況, 如<constructor-arg name="aa">, 那麼這種狀況就須要首先肯定構造函數中的參數名稱.
    
       獲取參數名稱能夠有兩種方式, 一種時經過註解的方式直接獲取, 另外一種就是使用Spirng中提供的工具類 ParameterNameDiscoverer 來獲取. 構造函數, 參數名稱, 參數類型, 參數值都肯定後就能夠鎖定構造函數以及轉換對應的參數類型了.
    
    3. 根據肯定的構造函數轉換對應的參數類型
    
       主要是使用Spring 中提供的類型轉換器或者用戶提供的自定義類型轉換器進行轉換.
    
    4. 構造函數不肯定性的驗證
    
       固然, 有時候即便構造函數, 參數名稱, 參數類型, 參數值都肯定後也不必定會直接鎖定構造函數, 不一樣構造函數的參數爲父子關係, 因此Spring 在最後又作了一次驗證.
    
    5. 根據實例化策略以及獲得的構造函數及構造函數參數實例化Bean. 
    
    複製代碼
    • instantiateBean

      經歷了帶有參數的構造函數的實例構造, 相信你會輕鬆愉快的理解不帶參數的構造函數的實例化過程.

      org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#instantiateBean

      protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
      		try {
      			Object beanInstance;
      			final BeanFactory parent = this;
      			if (System.getSecurityManager() != null) {
      				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
      						getInstantiationStrategy().instantiate(mbd, beanName, parent),
      						getAccessControlContext());
      			}
      			else {
      				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
      			}
      			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      			initBeanWrapper(bw);
      			return bw;
      		}
      		catch (Throwable ex) {
      			throw new BeanCreationException(
      					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
      		}
      	}
      
      複製代碼

      此方法並無實質性的邏輯, 帶有參數的實例構造中, Spring 把經理都放在了構造函數以及參數的匹配上, 因此若是沒有參數的話那將是很是簡單的一件事, 直接調用實例化策略進行實例化就能夠了.

    • 實例化策略

      實例化過程當中反覆提到過實例化策略, 那這又是作什麼用的呢? 其實, 通過前面的分析, 咱們已經獲得了足以實例化的全部相關信息, 徹底可使用最簡單的反射方法直接反射來構造實例對象, 可是Spring卻並無這麼作.

      org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.String, org.springframework.beans.factory.BeanFactory)

      @Override
      	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
      		// Don't override the class with CGLIB if no overrides.
          // 若是有須要覆蓋或者動態替換的方法則固然須要使用cglib進行動態代理, 由於能夠在建立代理的同時將動態方法織入類中, 可是若是沒有須要動態代理改變的方法, 爲了方便直接反射就能夠了
      		if (!bd.hasMethodOverrides()) {
      			Constructor<?> constructorToUse;
      			synchronized (bd.constructorArgumentLock) {
      				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
      				if (constructorToUse == null) {
      					final Class<?> clazz = bd.getBeanClass();
      					if (clazz.isInterface()) {
      						throw new BeanInstantiationException(clazz, "Specified class is an interface");
      					}
      					try {
      						if (System.getSecurityManager() != null) {
      							constructorToUse = AccessController.doPrivileged(
      									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
      						}
      						else {
      							constructorToUse = clazz.getDeclaredConstructor();
      						}
      						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
      					}
      					catch (Throwable ex) {
      						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
      					}
      				}
      			}
      			return BeanUtils.instantiateClass(constructorToUse);
      		}
      		else {
      			// Must generate CGLIB subclass.
      			return instantiateWithMethodInjection(bd, beanName, owner);
      		}
      	}
      
      複製代碼

      看了上面兩個函數後彷佛咱們已經感覺到了 Spring 的良苦用心以及爲了能更方便的使用 Spring 而作了大量的工做. 程序中, 首先判斷若是 beanDefinition.getMethodOverrides() 爲空也就是用戶沒有使用 replace 或者 lookup 的配置方法, 那麼直接使用放射的方式, 簡單快捷, 可是若是使用了這兩個特性, 在直接使用反射的方式建立實例就不妥了, 由於須要將這兩個配置提供的功能切入進去, 因此就必需要使用動態代理的方式將包含兩個特性所對應的邏輯的攔截加強器設置進去, 這樣才能夠保證在調用方法的時候會被相應的攔截器加強, 返回值爲包含攔截器的代理實例.

5.7.2 記錄建立bean的ObjectFactory

在 doCreate 函數中有這樣一段代碼:

/* 是否須要提前曝光: 單例&容許循環依賴&當前bean正在建立中, 檢測循環依賴 */
 		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
 		if (earlySingletonExposure) {
 			if (logger.isDebugEnabled()) {
 				logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
 			}
			// 爲避免後期循環依賴, 能夠在bean初始化完成前將建立實例的ObjectFactory加入工廠
 			addSingletonFactory(beanName, new ObjectFactory<Object>() {
 				@Override
 				public Object getObject() throws BeansException {
 					// 對 bean 再一次依賴引用, 主要應用 SmartInstantiationAware BeanPostProcessor, 其中咱們熟悉的AOP就是在這裏將advice動態織入bean中, 若沒有則直接返回bean, 不作任何處理
 					return getEarlyBeanReference(beanName, mbd, bean);
 				}
 			});
 		}

複製代碼

這段代碼不是很複雜, 可是不少人不是太理解這段代碼的做用, 並且, 這段代碼僅今後函數中去理解也很難弄懂其中的含義, 咱們須要從全局的角度去思考 Spring 的依賴解決辦法.

  • earlySingletonExposure: 從字面的意思就是提前曝光的單例, 咱們暫不定義它的學名叫什麼, 咱們感興趣的是有哪些條件影響這個值.

  • mbd.isSingleton(): 沒有太多能夠解釋的, 此 RootBeanDefinition 表明的是不是單例.

  • this.allowCircularReferences: 是否容許循環依賴, 很抱歉, 並無找到在配置文件中如何配置, 可是在 AbstractRefreshableApplicationContext 中提供了設置函數, 能夠經過硬編碼的方式進行設置或者能夠經過自定義命名空間進行配置, 其中硬編碼的方式代碼以下:

    ClassPathXmlApplicationContext bf = new ClassPathXmlApplicationContext("aspectTest.xml");
    bf.setAllowBeanDefinitionOverriding(false);
    
    複製代碼
  • isSingletonCurrentlyCreation(beanName): 該 bean 是否在建立中, 在 Spring 中, 會有個專門的屬性默認爲 DefaultSingletonBeanRegistry 的 singletonsCurrentlyInCreation 來記錄bean的加載狀態, 在bean開始建立前會將 beanName 記錄在屬性中, 在 bean 建立結束後會將 beanName 從屬性中移除, 那麼咱們跟隨代碼一路走來但是對這個屬性記錄並無多少印象, 這個狀態是在哪裏記錄的呢? 不一樣 scope 的記錄位置並不同, 咱們以 singleton 爲例, 在 singleton 下記錄屬性的函數是在 DefaultSingletonBeanRegistry 類的 public Object getSingleton(String beanName, ObjectFactory singletonFactory) 函數的 beforeSingletonCreation(beanName) 和 afterSingletonCreation(beanName) 中, 在這兩段函數中分別 this.singletonsCurrentlyInCreation.add(beanName) 與this.singletonsCurrentlyInCreation.remove(beanName) 來進行狀態的記錄與移除.

通過以上分析咱們瞭解變量 earlySingletonExposure 是否單例, 是否容許循環依賴, 是否對應的 bean 正在建立的 條件的綜合. 當這3個條件都知足時會執行 addSingletonFactory 操做, 那麼加入SingletonFactory 的做用是什麼呢? 又是在何時調用的呢?

咱們仍是以最簡單AB循環依賴爲例, 類A中含有屬性類B, 而類B中又會含有屬性類A, 那麼初始化beanA的過程如圖所示:

graph TD
		建立beanA-->開始建立bean記錄beanNameA
		subgraph A
		開始建立bean記錄beanNameA-->addSingletonFactoryA(addSingletonFactory)
		addSingletonFactoryA(addSingletonFactory)-->populateBean填充A屬性
		populateBean填充A屬性-->結束建立bean移除beanNameA
		end
		
		subgraph B
		populateBean填充A屬性-->開始建立bean記錄beanNameB
		開始建立bean記錄beanNameB-->addSingletonFactoryB(addSingletonFactory)
		addSingletonFactoryB(addSingletonFactory)-->populateBean填充B屬性
		populateBean填充B屬性-->結束建立bean移除beanNameB
		end
		
		subgraph C
		populateBean填充B屬性-->getBeanA
		end
複製代碼

上圖展現了建立beanA的流程, 從圖中咱們看到, 在建立A的時候首先會記錄類A所對應的beanName, 並將beanA的建立工廠加入緩存中, 而在對A的屬性填充也就是調用populate方法的時候又會再一次的對B進行遞歸建立, 一樣的, 由於在B中一樣存在A屬性, 所以在實例化B的pupulate方法中優惠再次的初始化B, 也就是圖形的最後, 調用getBean(A), 關鍵是在這裏, 在這個函數中並非直接去實例化A, 而是先去檢查緩存中是否有已經建立號的對應的bean, 或者是否已經建立好的ObjectFactory, 而此時對於A的ObjectFactory咱們早已建立, 因此便不會再去向後執行, 而是直接調用ObjectFactory去建立A. 這裏最關鍵的是 ObjectFactory 的實現.

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
 		if (earlySingletonExposure) {
 			if (logger.isTraceEnabled()) {
 				logger.trace("Eagerly caching bean '" + beanName +
 						"' to allow for resolving potential circular references");
 			}
 			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
 		}
     
     	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
     		Object exposedObject = bean;
     		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
     			for (BeanPostProcessor bp : getBeanPostProcessors()) {
     				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
     					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
     					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
     				}
     			}
     		}
     		return exposedObject;
     	}

複製代碼

在 getEarlyBeanReference 函數中並無太多的邏輯處理, 或者說除了後處理器的調用外, 沒有別的處理工做, 根據以上分析, 基本能夠理清 Spring 處理循環依賴的解決辦法, 在B中建立依賴A時經過ObjectFactory提供的實例方法來中斷A中的屬性填充, 使B中持有的A僅僅是剛剛初始化並無填充任何屬性的A, 而這正初始化A的步驟仍是在最開始建立A的時候進行的, 可是由於A與B中的A所表示的屬性地址是同樣的, 因此在A中建立好的屬性填充天然能夠經過B中的A獲取, 這樣就解決了循環依賴的問題.

5.7.3 屬性注入

在瞭解循環依賴的時候, 咱們曾經反覆提到了 populateBean 這個函數, 也多少了解了這個函數的主要功能就是屬性填充, 那麼到底是如何實現填充的呢?

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
     		if (bw == null) {
     			if (mbd.hasPropertyValues()) {
     				throw new BeanCreationException(
     						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
     			}
     			else {
     				// 沒有可填充的屬性
     				return;
     			}
     		}
     
     		// 給 InstantiationAwareBeanPostProcessors 最後一次機會在屬性設置前來改變 bean
     		// 如: 能夠用來支持屬性注入的類型
     		boolean continueWithPropertyPopulation = true;
     
     		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
     			for (BeanPostProcessor bp : getBeanPostProcessors()) {
     				if (bp instanceof InstantiationAwareBeanPostProcessor) {
     					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
              // 返回值爲是否繼續填充bean 
     					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
     						continueWithPropertyPopulation = false;
     						break;
     					}
     				}
     			}
     		}
     
         // 若是後處理器發出中止填充命令則終止後續的進行
     		if (!continueWithPropertyPopulation) {
     			return;
     		}
     
     		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
     
     		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
     			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
     			// 根據名稱自動注入
     			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
     				autowireByName(beanName, mbd, bw, newPvs);
     			}
     			// 根據類型自動注入
     			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 (hasInstAwareBpps) {
     			if (pvs == null) {
     				pvs = mbd.getPropertyValues();
     			}
     			for (BeanPostProcessor bp : getBeanPostProcessors()) {
     				if (bp instanceof InstantiationAwareBeanPostProcessor) {
     					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
              // 對全部須要依賴檢查的屬性進行後置處理
     					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
     					if (pvsToUse == null) {
     						if (filteredPds == null) {
     							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
     						}
     						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
     						if (pvsToUse == null) {
     							return;
     						}
     					}
     					pvs = pvsToUse;
     				}
     			}
     		}
     		if (needsDepCheck) {
     			if (filteredPds == null) {
            // 依賴檢查, 對應 depends-on 屬性, 3.0已經棄用此屬性 
     				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
     			}
     			checkDependencies(beanName, mbd, filteredPds, pvs);
     		}
     
     		if (pvs != null) {
          // 將屬性應用到 bean 中 
     			applyPropertyValues(beanName, mbd, bw, pvs);
     		}
     	}

複製代碼

在 populateBean 函數中提供了這樣的處理流程:

  • InstantiationAwareBeanPostProcessor處理器的 postProcessAfterInstantiation 函數的應用, 次函數能夠控制程序是否繼續進行屬性填充.
  • 根據注入類型 (byName/byType), 提取依賴的 bean; 並統一存入 PropertyValue 中.
  • 應用 InstantiationAwareBeanPostProcessor 處理器的 postProcessPropertyValues 方法, 對屬性獲取完畢填充前對屬性的再次處理, 典型應用是 RequiredAnnotationBeanPostProcessor 類中對屬性的驗證.
  • 將全部 PropertyValues 中的屬性填充至 BeanWrapper 中.

在上面的步驟中有幾個地方是咱們比較感興趣的, 他們分別是依賴注入(autowireByName/autowireByType) 以及屬性填充, 那麼, 接下里進一步分析這幾個功能的實現細節.

  1. autowireByName

    上文提到根據注入類型 (byName/byType), 提取依賴的bean嗎並統一存入PropertyValues中, 那麼咱們首先了解下 byName 功能是如何實現的.

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireByName

    protected void autowireByName( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    
    	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    	for (String propertyName : propertyNames) {
    		if (containsBean(propertyName)) {
    			Object bean = getBean(propertyName);
    			pvs.add(propertyName, bean);
    			registerDependentBean(propertyName, beanName);
    			if (logger.isTraceEnabled()) {
    				logger.trace("Added autowiring by name from bean name '" + beanName +
    						"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
    			}
    		}
    		else {
    			if (logger.isTraceEnabled()) {
    				logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
    						"' by name: no matching bean found");
    			}
    		}
    	}
    }
    
    複製代碼
  2. autowireByType

    autowireByType 與 autowireByName 對於咱們理解與使用來講複雜程度都很類似, 可是其實現功能的複雜度卻徹底不同.

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireByType

    protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    
    	TypeConverter converter = getCustomTypeConverter();
    	if (converter == null) {
    		converter = bw;
    	}
    
    	Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
    	// 尋找bw中須要依賴注入的屬性
    	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    	for (String propertyName : propertyNames) {
    		try {
    			PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
    			// Don't try autowiring by type for type Object: never makes sense,
    			// even if it technically is a unsatisfied, non-simple property.
    			if (Object.class != pd.getPropertyType()) {
    				// 探測定位屬性的 set 方法
    				MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
    				// Do not allow eager init for type matching in case of a prioritized post-processor.
    				boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
    				DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
    				// 解析指定 beanName 的屬性所匹配的值, 並把解析到的屬性名稱存儲在 autowireBeanName 中, 當屬性存在多個封裝的 bean 時如:
    				// @Autowired private List<A> aList; 將會找到全部匹配A類型的bean並將其注入
    				Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
    				if (autowiredArgument != null) {
    					pvs.add(propertyName, autowiredArgument);
    				}
    				for (String autowiredBeanName : autowiredBeanNames) {
    					// 註冊依賴
    					registerDependentBean(autowiredBeanName, beanName);
    					if (logger.isTraceEnabled()) {
    						logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
    								propertyName + "' to bean named '" + autowiredBeanName + "'");
    					}
    				}
    				autowiredBeanNames.clear();
    			}
    		}
    		catch (BeansException ex) {
    			throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
    		}
    	}
    }
    
    複製代碼

    實現根據名稱自動匹配的第一步就是尋找 bw 中須要依賴注入的屬性, 一樣對於根據類型自動匹配的實現來說第一步也是尋找bw中須要依賴注入的屬性, 而後遍歷這些屬性並尋找類型匹配的bean, 其中最複雜的就是尋找類型匹配的 bean. 同事 Spring 中提供了對集合的類型注入的支持. 如使用註解的方式:

    @Autowired private List<Test> tests;
    
    複製代碼

    Spring 將會把全部與 Test 匹配的類型找出來並出入到 tests 屬性中, 正式因爲這一因素, 因此在 autowireByType 函數中, 新建了局部遍歷 autowiredBeanNames, 用於存儲全部依賴的 bean, 若是隻是對非集合類的屬性注入來講, 此屬性並沒有用處.

    對於尋找類型匹配的邏輯實現封裝在了 resolveDependency 函數中.

    DefaultListableBeanFactory#resolveDependency

    @Override
    @Nullable
    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()) {
    // ObjectFactory 類注入的特殊處理
    		return new DependencyObjectProvider(descriptor, requestingBeanName);
    	}
    	else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
    // javaxInjectProviderClass 類注入的特殊處理
    		return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
    	}
    	else {
    		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
    				descriptor, requestingBeanName);
    		if (result == null) {
     // 通用邏輯處理
    			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
    		}
    		return result;
    	}
    }
    
    @Nullable
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    	/* 用於支持 Spring 中新增的註解 @Value */
    	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());
    			try {
    				return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
    			}
    			catch (UnsupportedOperationException ex) {
    				// A custom TypeConverter which does not support TypeDescriptor resolution...
    				return (descriptor.getField() != null ?
    						converter.convertIfNecessary(value, type, descriptor.getField()) :
    						converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
    			}
    		}
    
    		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) {
    			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);
    		}
    		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);
    	}
    }
    
    複製代碼

    尋找類型的匹配執行順序時, 首先嚐試使用解析器進行解析, 若是解析器沒有成功解析, 那麼多是使用默認的解析器沒有作任何處理, 或者是使用了自定義的解析器, 可是對於集合等類型來講並不在解析範圍以內, 因此再次對不一樣類型進行不一樣狀況的處理, 雖然說對於不一樣了性處理方式不一致, 可是大體的思路仍是很類似的, 因此函數中只對數組類型進行了詳細的註釋.

  3. applyPropertyValues

    程序運行到這裏, 已經完成了對全部注入屬性的獲取, 可是獲取的屬性是以Propertyvalues形式存在的, 還並無應用到已經實例化的bean中, 這一工做是在applyPropertyValues中.

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues

    protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    	if (pvs == null || pvs.isEmpty()) {
    		return;
    	}
    
    	MutablePropertyValues mpvs = null;
    	List<PropertyValue> original;
    
    	if (System.getSecurityManager() != null) {
    		if (bw instanceof BeanWrapperImpl) {
    			((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
    		}
    	}
    
    	if (pvs instanceof MutablePropertyValues) {
    		mpvs = (MutablePropertyValues) pvs;
        // 若是mpvs中的值已經被轉換爲對應的類型那麼能夠直接設置到beanwrapper中
    		if (mpvs.isConverted()) {
    			// Shortcut: use the pre-converted values as-is.
    			try {
    				bw.setPropertyValues(mpvs);
    				return;
    			}
    			catch (BeansException ex) {
    				throw new BeanCreationException(
    						mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    			}
    		}
    		original = mpvs.getPropertyValueList();
    	}
    	else {
        // 若是pvs並非使用MutablePropertyValues封裝的類型, 那麼直接使用原始的屬性獲取方法
    		original = Arrays.asList(pvs.getPropertyValues());
    	}
    
    	TypeConverter converter = getCustomTypeConverter();
    	if (converter == null) {
    		converter = bw;
    	}
      // 獲取對應的解析器
    	BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
    
    	// Create a deep copy, resolving any references for values.
    	List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
    	boolean resolveNecessary = false;
      // 遍歷屬性, 將屬性轉換爲對應類的對應屬性的類型
    	for (PropertyValue pv : original) {
    		if (pv.isConverted()) {
    			deepCopy.add(pv);
    		}
    		else {
    			String propertyName = pv.getName();
    			Object originalValue = pv.getValue();
    			Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
    			Object convertedValue = resolvedValue;
    			boolean convertible = bw.isWritableProperty(propertyName) &&
    					!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
    			if (convertible) {
    				convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
    			}
    			// Possibly store converted value in merged bean definition,
    			// in order to avoid re-conversion for every created bean instance.
    			if (resolvedValue == originalValue) {
    				if (convertible) {
    					pv.setConvertedValue(convertedValue);
    				}
    				deepCopy.add(pv);
    			}
    			else if (convertible && originalValue instanceof TypedStringValue &&
    					!((TypedStringValue) originalValue).isDynamic() &&
    					!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
    				pv.setConvertedValue(convertedValue);
    				deepCopy.add(pv);
    			}
    			else {
    				resolveNecessary = true;
    				deepCopy.add(new PropertyValue(pv, convertedValue));
    			}
    		}
    	}
    	if (mpvs != null && !resolveNecessary) {
    		mpvs.setConverted();
    	}
    
    	// Set our (possibly massaged) deep copy.
    	try {
    		bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    	}
    	catch (BeansException ex) {
    		throw new BeanCreationException(
    				mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    	}
    }
    
    複製代碼

5.7.4 初始化bean

你們應該記得在 bean 配置時 bean 中有一個 init-method 的屬性, 這個屬性的做用是在 bean 實例化前調用 init-method 指定的方法來根據用戶業務進行相應的實例化. 咱們如今就已經進入這個方法了, 首先看一下這個方法的執行位置, Spring 中程序已經執行過 bean 的實例化, 而且進行了屬性的填充, 而就在這時將會調用用戶設定的初始化方法.

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged(new PrivilegedAction<Object>() {
			@Override
			public Object run() {
				invokeAwareMethods(beanName, bean);
				return null;
			}
		}, getAccessControlContext());
	}
	else 
    // 對特殊的 bean 處理: Aware, BeanClassLoaderAware, BeanFactoryAware
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
    // 應用後處理器
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
    // 激活用戶自定義的 init 方法
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}

	if (mbd == null || !mbd.isSynthetic()) {
    // 後處理器應用
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}
	return wrappedBean;
}

複製代碼

雖說此函數的主要目的是進行客戶設定的初始化方法的調用, 可是除此以外還有些其餘必要的工做.

  1. 激活 Aware 方法

    在分析其原理以前, 咱們先了解一下 Aware 的使用. Spring 中提供了一些 Aware 相關接口, 好比 BeanFactoryAware, ApplicationContextAware, ResourceLoaderAware, ServletContextAware等, 實現這些Aware 接口的 bean 在被初始化以後, 能夠取得一些相應的資源, 例如實現 BeanFactoryAware 的 bean 在初始後, Spring 容器將會注入 BeanFactory 的實例, 而實現 ApplicationContextAware 的 bean, 在 bean 被初始後, 將會被注入 ApplicationContext 的實例等, 咱們首先經過示例方法來了解一下 Aware 的應用.

    (1) 定義普通 bean

    public class Hello {
      public void say() {
        System.out.println("hello");
      }
    }
    
    複製代碼

    (2) 定義 BeanFactoryAware 類型的 bean

    public class Test implements BeanFactoryAware {
      private BeanFactory beanFactory;
      
      // 聲明 bean 的時候 Spring 會自動注入 BeanFactory
      @Override
      public void setBeanFactory(BeanFactory beanFactory) throws BeanException {
        this.beanFactory = beanFactory;
      }
      
      public void testAware() {
        // 經過 hello 這個 bean id 從 beanFactory 獲取實例
        Hello hello = (Hello) beanFactory.getBean("hello");
        hello.say();
      }
      
    }
    
    複製代碼

    (3) 使用main方法測試

    public static void main(String[] s) {
      ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
      Test test = (Test) ctx.getBean("test");
      test.testAware();
    }
    
    複製代碼

    裕興測試類, 控制檯輸出:

    hello
    
    複製代碼

    按照上面的方法咱們能夠獲取到Spring 中BeanFactory, 而且能夠根據 BeanFactory 獲取全部 bean, 以及進行相關設置. 固然還有其餘 Aware 的使用方法都大同小異, 看一下 Spring 的實現方式, 便會使用了.

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods

    private void invokeAwareMethods(final String beanName, final Object bean) {
    	if (bean instanceof Aware) {
    		if (bean instanceof BeanNameAware) {
    			((BeanNameAware) bean).setBeanName(beanName);
    		}
    		if (bean instanceof BeanClassLoaderAware) {
    			((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
    		}
    		if (bean instanceof BeanFactoryAware) {
    			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    		}
    	}
    }
    
    複製代碼
  2. 處理器的應用

    BeanPostProcessor 相信你們都不陌生, 這是 Spring 中開放式架構中一個必不可少的亮點, 給用戶充足的權限去更改或者擴展 Spring, 而除了 BeanPostProcessor 外還有不少其餘的 PostProcessor, 固然啊部分都是以此爲基礎, 繼承自BeanPostProcessor. BeanPostProcessor的使用位置就是這裏, 在調用客戶自定義初始化方法前以及調用自定義初始化方法後分別會調用 BeanPostProcessor 的 postProcessBeforeInitiallization 和 postProcessAfterInitialization 方法, 使用戶能夠根據本身的業務需求進行響應的處理.

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
    
    	Object result = existingBean;
    	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
    		result = beanProcessor.postProcessBeforeInitialization(result, beanName);
    		if (result == null) {
    			return result;
    		}
    	}
    	return result;
    }
    
    複製代碼

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
    
    	Object result = existingBean;
    	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
    		result = beanProcessor.postProcessAfterInitialization(result, beanName);
    		if (result == null) {
    			return result;
    		}
    	}
    	return result;
    }
    
    複製代碼
  3. 激活自定義的init方法

    客戶定製的初始化方法除了咱們熟知的使用配置init-method外, 還有使自定義的bean實現 InitializingBean 接口, 並在 afterPropertiesSet 中實現本身的初始化業務邏輯.

    init-method 與 afterPropertiesSet 都是在初始化 bean 時執行, 執行順序是 afterPropertiesSet 先執行, 而 init-method 後執行.

    在 invokeInitMethods 方法中就實現了這兩個步驟的初始化方法調用.

    protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
    	// 首先會檢查是不是 InitializingBean , 若是是的話須要調用 afterPropertiesSet 方法
    	boolean isInitializingBean = (bean instanceof InitializingBean);
    	if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    		if (logger.isDebugEnabled()) {
    			logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
    		}
    		if (System.getSecurityManager() != null) {
    			try {
    				AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
    					@Override
    					public Object run() throws Exception {
    						((InitializingBean) bean).afterPropertiesSet();
    						return null;
    					}
    				}, getAccessControlContext());
    			}
    			catch (PrivilegedActionException pae) {
    				throw pae.getException();
    			}
    		}
    		else {
          // 屬性初始化後的處理
    			((InitializingBean) bean).afterPropertiesSet();
    		}
    	}
    
    	if (mbd != null) {
    		String initMethodName = mbd.getInitMethodName();
    		if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
    				!mbd.isExternallyManagedInitMethod(initMethodName)) {
          // 調用自定義初始化方法
    			invokeCustomInitMethod(beanName, bean, mbd);
    		}
    	}
    }
    
    複製代碼

5.7.5 註冊DisposableBean

Spring 中不但提供了對於初始化方法的擴展入口, 一樣也提供了銷燬方法的擴展入口, 對於銷燬方法的擴展, 除了咱們熟知的配置屬性 destroy-method 方法外, 用戶還能夠註冊後處理器 DestructionAwareBeanPostProcessor 來統一處理 bean 的銷燬方法, 代碼以下:

org.springframework.beans.factory.support.AbstractBeanFactory#registerDisposableBeanIfNecessary

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
	AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
	if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
		if (mbd.isSingleton()) {
			// 單例模式下注冊須要銷燬的 bean , 此方法中會處理實現 DisposableBean 的 bean, 而且對全部的 bean 使用 DestructionAwareBeanPostProcessor 處理 DisposableBean DestructionAwareBeanPostProcessors
			registerDisposableBean(beanName,
					new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
		}
		else {
			// 自定義 scope 的處理
			Scope scope = this.scopes.get(mbd.getScope());
			if (scope == null) {
				throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
			}
			scope.registerDestructionCallback(beanName,
					new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
		}
	}
}

複製代碼
相關文章
相關標籤/搜索