走心Springboot源碼解析: 5、refresh方法 getBean解析

打個廣告

我的想寫《springboot源碼解析》這一系列好久了,可是一直角兒心底的知識積累不足,因此一直沒有動筆。 因此想找一些小夥伴一塊兒寫這一系列,互相糾錯交流學習。 若是有小夥伴有興趣一塊兒把這一系列的講解寫完的話,加下我微信:13670426148,咱們一塊兒完成,當交流學習。 後期還想寫一系列介紹rpc框架的,不過要再過一陣子了,先把springboot的寫完java

前言

主要補充講 refresh 方法,爲ioc 容器實例化全部的bean作一個深刻解析,前面第4節講了配置類的讀取並實例化,那普通bean 的實例化在何時呢?,其中代碼設計中的依賴注入是怎麼解決的呢?讓咱們揭開表面Ioc的面紗。spring

refresh總方法

延續上一篇,繼續擺上refresh方法代碼數組

public void refresh() throws BeansException, IllegalStateException {
        //由於該過程必須是同步的,因此進行加鎖處理
        synchronized(this.startupShutdownMonitor) {
            // 1. 容器刷新前的準備,設置上下文,獲取屬性,驗證必要的屬性
            this.prepareRefresh();
            // 2. 銷燬原先的 beanFactory,建立新的bean工廠,
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            // 3. 配置標準的beanFactory,設置ClassLoader,設置SpEL表達式解析器等等
            this.prepareBeanFactory(beanFactory);

            try {
                // 4. 添加一個BeanPostProcessor到bean工廠中,類型爲WebApplicationContextServletContextAwareProcessor(this)
                // 任意Bean均可以很方便的獲取到ServletContext。
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                // 5. 實例化全部剩餘的(非懶加載)單例
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

複製代碼

咱們重點講的就是第5步, this.finishBeanFactoryInitialization(beanFactory),實例化全部剩餘的(非懶加載)單例。緩存

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // Initialize conversion service for this context.
        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));
        }

        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // Stop using the temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(null);

        // Allow for caching all bean definition metadata, not expecting further changes.
        beanFactory.freezeConfiguration();

        //這個方法裏的東西呢咱們只需關注這一行便可
        beanFactory.preInstantiateSingletons();
    }

複製代碼

開始獲取全部 beanDefinitionspringboot

public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// 獲取全部的 beanDefinition
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
	
		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
                 // 獲得 beanDefinition
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                       // 非抽象類、單例、非懶加載的
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                       // 若是是 FactoryBean
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
              
							getBean(beanName);
						}
					}
				}
                              // 若是不是 FactoryBean, 
				else {
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans... 
  	          // 出發回調,暫時不知道是什麼,作個mark
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}


複製代碼

能夠看出到最後都是統一走的 getBean() 方法微信

開始走進 getBean方法中

lass AbastractBeanFactory {
  
  
  	@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 {
		// 1. 別名轉換
		final String beanName = transformedBeanName(name);
		Object bean;
		
		// 2. 檢查緩存中是否存在 beanName 對應的 bean
                // 2.1 
		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 + "'");
				}
			}
                         // 2.2 從bean 中獲取對象,
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		// 3. 若是緩存中不存在 beanName 對應的 bean,則
		else {
			// 3.1 若是原型模式下,若是指定beanName 的類正在建立中,則拋出異常,緣由看後面解釋
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
                       // containsBeanDefinition : beanDefinitionMap.containsKey(beanName);
                      // 就是若是 DefaultListableBeanFactory 中不包含,就去查 DefaultListableBeanFactory 的父類,看與沒有包含該 beanDefinition 
			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);
			}
			// 若是 DefaultListableBeanFactory 中已經存在了 該 beanDefinition
			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// 3.2 找到 mbd 的依賴的 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 + "'");
						}
            // 先實例化其依賴bean
						registerDependentBean(dep, beanName);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// 3.3 若是 beanDefinition 是 單例的bean ,先看單例 bean 實例化過程, 從頭至尾加載單例 bean
				if (mbd.isSingleton()) {
                                        // 3.3.1 調用 建立bean 的方法
					sharedInstance = getSingleton(beanName, () -> {
						try {
                                                      // 這裏建立原始的 bean 了
							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;
						}
					});
                                      // 3.3.2 獲得最終的bean ,由於可能會有 FactoryBean ,咱們要的實例實際上是他的 factory-method 返回的對象纔對
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
		        	   // 若是 beanDefinition 是 原型的bean, 
				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;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		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;
	}
}

複製代碼

步驟大概能夠分爲:數據結構

(1)轉換對應的 beanName 由於傳入的名字多是 FactoryBean 的name, 格式爲 &xxx, 還有多是別名alias,處理方式能夠是app

  • 去除 FactoryBean 的修飾符, 也若是是 name = '&aa', 那麼就會去除 &, 獲得了 aa
  • 別名的狀況,是取別名指定的最終 beanName, 假設別名A 指向B, 而B指向了C, transformedBeanName(A) 獲得的結果爲 C

(2) 嘗試從緩存中加載單例框架

  • spring 會把已經加載了的 bean 存在緩存中,一個 map 格式的內存數據

(3) 從頭開始加載單例beanless

sharedInstance 已是bean 的原始形態了, 可是他並不必定使咱們最終想要的 bean。 有多是一個工廠 bean , 可是這裏獲得的是bean 的初始狀態,咱們真正須要的是工廠 bean 中定義的, factory-method 方法中返回的 bean, 而getObjectForBeanInstance 就是作這個工做的。

下面分開介紹 「 嘗試從緩存中加載單例」 和 "真正bean 的實例化"

嘗試從緩存中加載單例

show 代碼

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  
	final String beanName = transformedBeanName(name);
		Object bean;

		// 1. 嘗試從緩存中獲取 bean
		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 + "'");
				}
			}
                      // 2. 處理 FactoryBean 的狀況, 獲取其 factory-method 方法中返回的最終Bean
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
}

複製代碼

1. 緩存中獲取bean 流程

單例 bean 在同一個容器內只會被建立一次,後續再獲取 bean 就直接從單例緩存中獲取,固然也只是嘗試加載,首先嚐試從緩存中加載,而後再次嘗試從 singletonFactory 中加載.

由於在建立單例 Bean 的時候,會存在依賴注入的狀況, 而在建立依賴的時候,爲了不循環依賴, Spring 建立 bean 的原則是不等 bean 建立完成就會將建立 bean 的 ObjectFactory 提前曝光加入到 緩存中, 一旦下一個 Bean 建立時候須要依賴上個 bean, 則直接使用 ObjectFactory

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
  
  	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
                // 若是獲取不到 嘗試從 earlySingletonObjects 中加載, earlySingletonObjects 裏是存放 ObjectFactory 的
                 // 加鎖
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
                                     // 根據 beanName 獲取 ObjectFactory 
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
                                                 // 當Bean ,會放到 earlySingletonObjects
						this.earlySingletonObjects.put(beanName, singletonObject);
                                                 // 已經獲取過的bean 對應的 ObjectFactory,,就會被從 singletonFactories 中 remove 掉
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}
  
複製代碼

這裏涉及到幾個 map , 分別是 singletonObjects、 singletonFactories、earlySingletonObjects、registerSingletons

  • Singletonobjects: 用於保存 beanName 和 建立的 bean 實例之間的關係, beanName --> beanInstance
  • singletonFactories : beanName -> 建立bean 的工廠 之間的關係, beanName -> ObjectFactory
  • earlySingletonObjects: beanName 和建立 bean 實例之間的關係,與 singletonObjects 不用在於,當一個單例Bean 被放到這裏後,那麼當bean 還在建立過程當中,就可經過 getBean方法獲取到了,目的是用來檢測循環引用的
  • registerSingletons: 保存當前全部已註冊的 bean

2. 從頭開始加載單例bean

在第一步的獲取不到,緩存中不存在咱們要的bean 的時候,就要主動去從頭開始 bean 的加載過程了

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { 

	// 從頭至尾加載單例 bean 開始
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
            	// 加鎖
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
                      // 判斷是否已經加載過了,確定是沒加載過才必須走下面的加載流程
			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 + "'");
				}
                                   // 1. 開始加載以前的處理, 把 beanName 加入到 singletonsCurrentlyInCreation 中
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
                                      // 2. 主要內容仍是 singletonFactory這個方法, singletonFactory是一個用來作回調的類
					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;
					}
                                         // 3. 加載完以後處理, 移除緩存中對該 beanName 的加載記錄
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}
} 

複製代碼

講解前面的3點內容

2.1 加載以前的處理

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
  // 很簡單, singletonsCurrentlyInCreation 這個list是用來存儲哪些 bean 正在加載的
	protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}
}
複製代碼

2.2 回調邏輯,真正的內容,加載bean

try {
	// 2. 主要內容仍是 singletonFactory這個方法, singletonFactory是一個用來作回調的類
	singletonObject = singletonFactory.getObject();
	newSingleton = true;
}
複製代碼

還記得 getSingleton 被調用時候的調用寫法嗎?因此真正執行的是 createBean(beanName, mbd, args) 方法

// 3.3 若是 beanDefinition 是 單例的bean ,先看單例 bean 實例化過程, 從頭至尾加載單例 bean
if (mbd.isSingleton()) {
	// 3.3.1 調用 建立bean 的方法
	sharedInstance = getSingleton(beanName, () -> {
	try {
	// 這裏建立原始的 bean 了
		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;
	}
});

複製代碼

2.3 加載以後的處理

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

其中最主要的仍是第二步的回調方法 createBean

回調方法 createBean

由於 createBean 篇幅過長,因此單獨拎出來說

預備

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

	if (logger.isTraceEnabled()) {
		logger.trace("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	try {
              // 處理 overwrite 屬性,不展開
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}

	try {
		//前置處理器處理邏輯, 超級重要的一個方法,就是這個方法實現咱們的aop、事務,bean。 可是這裏暫時不展開
		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);
	}

	try {
                  // 這裏纔是重點 doCreateBean
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
		// A previously detected exception with proper bean creation context already,
		// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
}

複製代碼

看到 doCreateBean了,感覺到內味了沒有, 通常 doxxx 方法纔是真正幹活的,看完前面的內容,你們應該都累了吧,先來個小插曲, 再進入 doCreateBean

循環依賴

循環依賴是指 兩個bean 互相依賴對方,最終造成閉環

假設A依賴B,B依賴C,C又依賴A,那麼當會形成

(1)實例化A的時候,會去實例化B -> (2)實例化B的時候,會去實例化C -> (3)實例化C的時候,從新實例化A,這樣就死循環了,程序永遠都不會中止

那什麼狀況時候會發生依賴呢?

在寫 spring 配置文件中,通常能夠經過兩種方式注入依賴屬性,一種是 setter 注入和 構造器注入

先複習一下構造器注入 和 'setter注入'

// --- 構造器注入
<bean name="springController" class="***.SpringController">  
	<!--(2)建立構造器注入,若是主類有帶參的構造方法則需添加此配置-->  
	<constructor-arg index="0" ref="springDao"></constructor-arg>  
	<constructor-arg index="1" ref="user"></constructor-arg>  
</bean>  
<bean name="springDao" class="**.SpringDao"></bean>  
<bean name="user" class="**.User"></bean>  
  
// --- setter注入
<bean name="springAction" class="***.SpringController">  
<!--(1)依賴注入,配置當前類中相應的屬性-->  
	<property name="springDao" ref="springDao"></property>  
</bean>  
<bean name="springDao" class="**.SpringDao"></bean>
複製代碼

其中構造器注入方式沒法解決循環依賴問題,而 spring 是如何解決循環依賴的呢?

經過setter注入方式生成的 bean 才能夠解決循環依賴問題

spring採用的方式是將 實例化bean 跟 注入屬性這兩步分開。

doCreateBean

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

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

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

		// 2. 判斷是否須要提前曝光, 
		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");
			}
      // 若是須要提前曝光(單例模式下解決循環依賴都是須要提前曝光的),就是在這裏把
			// ObjectFactory 是一個函數式接口,裏面惟一的方法是 () -> getEarlyBeanReference(beanName, mbd, bean)
      // 把 ObjectFactory 加入到 singletonObjects中
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
		
		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
      //3. 注入屬性,其中可能存在依賴與其餘bean , 則會遞歸初始化依賴的 bean
			populateBean(beanName, mbd, instanceWrapper);
			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);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					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 {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

複製代碼

代碼異常處理超級繁瑣,有點看不下去了,因此直接看重點便可。

1. 實例化 bean

BeanDifinition 轉換爲 BeanWrapper

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
  
  	
  	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// 根據 beanName 反射獲取 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());
		}

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}
		// 若是 beanDefinition 中存在 factoryMethodName 屬性,則會調用instantiateUsingFactoryMethod 根據配置生成bean ,這個不是重點不討論
		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) {
        //resolvedConstructorOrFactoryMethod 是用來判斷是否已經解析過,若是該bean 已經解析過則 resolved 爲 true
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
      // 若是已經解析過
		if (resolved) {
      // 這裏開始了構造器構造 bean 的過程
		// 一個類可能有多個構造器,因此Spring得根據參數個數、類型肯定須要調用的構造器
		// 在使用構造器建立實例後,Spring會將解析事後肯定下來的構造器或工廠方法保存在緩存中,避免再次建立相同bean時再次解析
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
        //2. 若是是已經解析過且無參的構造函數,,
				return instantiateBean(beanName, mbd);
			}
		}
		
    
		// 3. 若是是沒有解析過的bean ,則 構造函數必須先解析,以後再調用autowireConstructor 方法注入
    // determineConstructorsFromBeanPostProcessors 是根據 參數解析構造函數
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
      // 使用解析好的構造函數 構造bean
			return autowireConstructor(beanName, mbd, ctors, args);
		}
	
		// Preferred constructors for default construction?
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}
		// 使用默認的構造函數
		return instantiateBean(beanName, mbd);
	}
}
複製代碼

上面代碼有點複雜,直接看第三點便可, 一、2都是緩存的實現,直接看3.,,有兩個步驟 (1)根據解析構造函數 determineConstructorsFromBeanPostProcessors (2)根據構造函數實例化 bean

1. BeanWrapper

咱們必須弄明白一件事情,上面的步驟 doCreateBean 的目的是什麼? 看返回值,是 BeanWrapper 類型的結構

BeanWrapper 的實現類是 BeanWrapperImpl ,先看 BeanWrapperImpl 的類圖

實現的接口有:

PropertyAccessor: 具有對包裝bean 屬性的讀寫能力 ConfigurablePropertyAccessor:配置一些屬性,如設置 ConversionService、是否暴露舊值、嵌套注入時屬性爲 null 是否自動建立。 BeanWrapper: 對 bean 進行封裝。

暫時能夠認爲, BeanWrapperImpl 中包含了對 javaBean 屬性的操做。直接看 PropertyAccessor 內部的方法.

public interface PropertyAccessor {
    boolean isReadableProperty(String propertyName);
    boolean isWritableProperty(String propertyName);

    Class<?> getPropertyType(String propertyName) throws BeansException;
    TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException;

    Object getPropertyValue(String propertyName) throws BeansException;

    void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException;
    void setPropertyValue(PropertyValue pv) throws BeansException;
    void setPropertyValues(Map<?, ?> map) throws BeansException;
    void setPropertyValues(PropertyValues pvs) throws BeansException;

    void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown) throws BeansException;
    void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) throws BeansException;
}

複製代碼

暫時能夠認爲,提供了對 bean屬性的操做。 對 BeanWrapperImpl 有興趣的能夠看下文章: BeanWrapperImpl 講解

2. autowireConstructor 構造BeanWrapper

接下來這段代碼,超過了150行,建議各位客官先喝口水再看,前方高能

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {

		BeanWrapperImpl bw = new BeanWrapperImpl();
    // 處理了好比註冊解析器、value解析器等等,
		this.beanFactory.initBeanWrapper(bw);

		Constructor<?> constructorToUse = null;
		ArgumentsHolder argsHolderToUse = null;
		Object[] argsToUse = null;
		//若是 getBean 方法調用的時候指定方法參數那麼直接使用
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
      // 若是沒有指定參數,則去 spring 容器中獲取
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
        //獲取已緩存解析的構造函數或工廠方法(resolvedConstructorOrFactoryMethod----用於緩存已解析的構造函數或工廠方法)
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				////若是緩存不爲空,而且構造參數已經解析緩存了,(constructorArgumentsResolved爲包可見,用於表示構造參數狀態是否已經解析)
				// 顯然首次進來,都是爲null而且沒有被解析的
        if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached constructor...
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
      
      // 若是上面沒有解析過,顯然這裏參數就是null了,argsToUse也就還爲null Spring下面繼續解析
			if (argsToResolve != null) {
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
			}
		}

    //若是緩存的構造器不存在,就說明沒有bean進行過解析,須要去關聯對應的bean的構造器
		if (constructorToUse == null || argsToUse == null) {
			// 緩存中找不到構造器就救使用方法參數中傳進來的構造器
			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);
				}
			}

			if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
				Constructor<?> uniqueCandidate = candidates[0];
				if (uniqueCandidate.getParameterCount() == 0) {
					synchronized (mbd.constructorArgumentLock) {
						mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
						mbd.constructorArgumentsResolved = true;
						mbd.resolvedConstructorArguments = EMPTY_ARGS;
					}
					bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
					return bw;
				}
			}

			// 這裏 chosenCtors 確定是存在的.
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;
		
			int minNrOfArgs;
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				//解析對應的構造參數而後添加到ConstructorArgumentValues中
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				resolvedValues = new ConstructorArgumentValues();
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}
      
			//按照訪問方式和數量對構造器進行排序;public>protect>private,在同爲public時構造器入參多的排在前面
			// 因此排在第一位的,是public的,參數最多的構造器
			AutowireUtils.sortConstructors(candidates);
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set<Constructor<?>> ambiguousConstructors = null;
			LinkedList<UnsatisfiedDependencyException> causes = null;
			// 1. 構造函數肯定
      // 遍歷全部的構造函數
			for (Constructor<?> candidate : candidates) {
        // 構造函數的參數
				Class<?>[] paramTypes = candidate.getParameterTypes();

				if (constructorToUse != null && argsToUse != 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, candidates.length == 1);
					}
					catch (UnsatisfiedDependencyException ex) {
						if (logger.isTraceEnabled()) {
							logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
						}
						// Swallow and try next constructor.
						if (causes == null) {
							causes = new LinkedList<>();
						}
						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<>();
						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 != null) {
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}

		Assert.state(argsToUse != null, "Unresolved constructor arguments");
    // 最終最終最終最終實例化bean 並放入到 BeanWrapper 中
		bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
		return bw;
	}
複製代碼

看完了上面的方法,咱們緩一緩,其實說到底就是,構造參數的肯定, 構造函數的肯定,最後是根據實例化策略以及獲得的構造函數,構造參數實例化 bean , 代碼太長,對象結構太複雜,看起來真是很是痛苦, 可是不理解也不要緊,差很少往下看,要抓住重點便可。

instantiate 方法暫時能夠認爲是根據構造器反射生成類,可是其實不僅只是反射,還包含了aop織入的處理,此處不展開講。

2. 提早曝光,循環依賴處理

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

		// ......略
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
  	// 此時這個 bean 就是經過構造器生成的bean ,還沒進行屬性注入的
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		//...... 略
  	// 開始判斷是否須要提早曝光,這個判斷就不解釋了
		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");
			}
      // 把重點在這裏,把 ObjectFactory 添加到 singletonFactory 中
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
		// Initialize the bean instance.
		Object exposedObject = bean;
	
		try {
      //3. 注入屬性,其中可能存在依賴與其餘bean , 則會遞歸初始化依賴的 bean
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
  
  	//.....略
}

// 接上面的 getEarlyBeanReference()
// 第三個參數 bean 就是傳進來的 "還未進行屬性注入的bean" 
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {	
		Object exposedObject = bean;
  	// 這個是一些後置處理器的處理,跟切面有關,這裏只是討論ioc,暫時略
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		return exposedObject;
	}
複製代碼

能夠看出來, 解決循環依賴的作法就是在getBean 的時候提早暴露獲取未進行依賴注入的beanObjectFactory 到spring容器中, 而 objectFactory 的getobject() 方法, 最後返回的是 還未進行屬性注入的bean 或者 被後置處理器處理了的代理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;
	}
複製代碼

還記得 getBean() 獲取 bean的時候那段循環依賴處理時候的邏輯嗎,能夠往前翻上去看看. 暴露完以後,當注入屬性的時候,會先找到該 bean 依賴的實例並先調用 getBean() 方法實例化其bean,而其實獲取到的是ObjectFactory.get() 返回的bean。

參考一張圖

根據圖,總結起來,spring處理循環依賴的解決過程用文字描述: spring 把 構造器實例化bean注入依賴 兩個步驟分隔開來, 在初始bean(A)屬性注入過程要實例化依賴bean(B)的時候,若是依賴bean(B)也依賴了初始bean(A),在建立依賴bean(B)時候的構建初始bean(A)時經過ObjectFactory 提供的實例化方法來中斷初始bean(A)的屬性填充,使得依賴bean(B)中持有的初始bean(A) 僅僅是剛初始化並無填充任何屬性的初始bean(A),而最終初始bean(A)是會進行屬性填充的,因此依賴bean(B)中的初始bean(A)到最後會是一個完整的bean,這樣就解決了循環依賴的問題。

3. 屬性注入

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
  
  	// 注入屬性
  	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 {
				// Skip property population phase for null instance.
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		boolean continueWithPropertyPopulation = true;
		
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
        // 實例化操做的後置處理器 InstantiationAwareBeanPostProcessor
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
          // 執行後置處理器的 postProcessAfterInstantiation ,做用直接看方法名就看得出來了
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		if (!continueWithPropertyPopulation) {
			return;
		}
		// 我本身啓動的時候,這裏 pvs 的值是null
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
		// 這個爲 false.相信,因此下面不走,相信不少人會看書,或者其餘文章說走這裏進行autowire,可是springboot2.0我debug的時候不走這塊地方,因此我直接跳過....,處理 @Autowire跟 @Resource 的地方還在下面
		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}
	
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
        // pvs 是一個對象,裏面存在的內容爲null
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
          // 1. 調用InstantiationAwareBeanPostProcessor#postProcessProperties擴展方法,這裏處理@Value,@Autowired等註解。
					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) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}
}


複製代碼
1. 調用 InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor 有幾個實現類,分別是

  • AbractAutoProxyCreater
  • AutowiredAnnotationBeanPostProcessor : 負責處理@Value@Autowired
  • CommonAnnotationBeanPostProcessor : 負責處理 @Resource 註解
  • ImportAwareBeanPostProcessor
  • ImportAwareBeanPostProcessor
  • InstantiationAwareBeanPostProcessor
  • ScriptFactoryPostProcessor

先看 AutowiredAnnotationBeanPostProcessor

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
  
  // 處理 @Autowire 和 @Resource
  @Override
	public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
		//1. 獲取Class中關於屬性注入相關注解的元數據
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
      //2. 完成屬性注入操做
			metadata.inject(bean, beanName, pvs);
		}
		catch (BeanCreationException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}  
}
複製代碼

插入個小片斷,講講註解元數據 InjectionMetadata 的結構

InjectionMetadata

![image-20200609083031262](/Users/zhaogengren/Library/Application Support/typora-user-images/image-20200609083031262.png)

能夠看出來主要有三個內容, targetClass是類自己, injectedElements是類須要注入的 bean, 像我這個類有 4 個

public class InjectionMetadata {

	private static final Log logger = LogFactory.getLog(InjectionMetadata.class);
	
	private final Class<?> targetClass;

	private final Collection<InjectedElement> injectedElements;

	private volatile Set<InjectedElement> checkedElements;

  	public static abstract class InjectedElement {
		// 最主要的
		protected final Member member;

		protected final boolean isField;

		protected final PropertyDescriptor pd;

		protected volatile Boolean skip;

}
複製代碼

須要注入的 bean 信息封存在 InjectedElement 中,看一下InjectedElement 的結構, injectedElement 中最主要的是 Member,Member 接口是反射的用法,用來表示「類」中的一個成員(字段或方法)或構造函數。能夠表示的有

  • Constructor - 構造器

  • Executable - 可執行的類型,是Constructor和Method的父類

  • Field - 屬性

  • Method - 方法

假設咱們是以 @Autowire 經過注入屬性的方式注入的bean,那麼該 Member 的結構爲

![image-20200609084619209](/Users/zhaogengren/Library/Application Support/typora-user-images/image-20200609084619209.png)

InjectedElement 的實現有多種形式

  • AutowiredFieldElement : @Autowired 方式注入屬性時候的數據結構
  • AutowiredMethodElement: @Autowired 方式注入方法時候的數據結構
  • ResourceElement: @Resource 方式注入時候的數據結構

從新進入正題了

  1. 獲取 Class 中關於屬性注入相關注解的元數據
// 其中有3個參數進來, beanName 爲bean的名稱, clazz 爲bean的類型, pvs是一個PropertyValues中元素個數爲0的 PropertyValues
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
   // 獲取bean的緩存key.
   String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
   // 根據key獲得緩存裏面的依賴bean元數據.
   InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
   if (InjectionMetadata.needsRefresh(metadata, clazz)) {
      synchronized (this.injectionMetadataCache) {
         metadata = this.injectionMetadataCache.get(cacheKey);
         if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            if (metadata != null) {
               metadata.clear(pvs);
            }
            metadata = buildAutowiringMetadata(clazz);
            this.injectionMetadataCache.put(cacheKey, metadata);
         }
      }
   }
   return metadata;
}
複製代碼

由於是 @AutoWire 注入的,因此此時 InjectedElement 有兩種實現分別是:AutowiredFieldElementAutowiredMethodElement,由於@Autowired 能夠注入屬性也能夠注入方法。

2. 開始注入
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
	
  Field field = (Field) this.member;
	Object value;
	//是否去查找緩存
	if (this.cached) {
		value = resolvedCachedArgument(beanName, this.cachedFieldValue);
	}
	else {
   // desc中存了依賴bean的Field 信息
		DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
		desc.setContainingClass(bean.getClass());
		Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
		TypeConverter typeConverter = beanFactory.getTypeConverter();
		try {
			//建立依賴對象bean 返回其對象值 (重點)
			value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
		}
		catch (BeansException ex) {
			throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
		}
		synchronized (this) {
			if (!this.cached) {
				if (value != null || this.required) {
					this.cachedFieldValue = desc;
           // 緩存DependencyDescriptor
					registerDependentBeans(beanName, autowiredBeanNames);
          // 緩存名稱beanName,直接根據名稱查找
					if (autowiredBeanNames.size() == 1) {
						String autowiredBeanName = autowiredBeanNames.iterator().next();
						if (beanFactory.containsBean(autowiredBeanName)) {
							if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
								this.cachedFieldValue = new ShortcutDependencyDescriptor(
										desc, autowiredBeanName, field.getType());
							}
						}
					}
				}
				else {
					this.cachedFieldValue = null;
				}
				this.cached = true;
			}
		}
	}
	if (value != null) {
		//反射,set依賴bean 完成注入
		ReflectionUtils.makeAccessible(field);
		field.set(bean, value);
	}

複製代碼

三步,第一是去緩存中找到

@Override
	public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		if (javaUtilOptionalClass == descriptor.getDependencyType()) {
			return new OptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName);
		}
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}
		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
        // 直接看 doResolveDependency
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

// descriptor 中存有依賴 Bean 的信息
public Object doResolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}
		  // 依賴 bean 的類型爲 type
			Class<?> type = descriptor.getDependencyType();
      // 獲取@Value註解的field, 這個值也能夠是 ${***} 格式的, 先跳過,主要講 @AutoWire 的解析
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String) {
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				return (descriptor.getField() != null ?
						converter.convertIfNecessary(value, type, descriptor.getField()) :
						converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
			}
		//若是標識@Autowired註解的屬性是複合類型,如Array,Collection,Map,
		// 從這個方法獲取@Autowired裏的值
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}
			//若是標識@Autowired註解的屬性是非複合類型,
			// 從這個方法獲取@Autowired裏的值, 重點,,下面講解
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			//若是沒有符合該類型的Bean
      if (matchingBeans.isEmpty()) {
        // 沒有找到,檢驗 @autowire 的 require 是否爲 true
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;
			//若是符合該類型的Bean有多個, 按照 @Primary、@Order、@PriorityOrder或Spring 指定的順序選擇
			if (matchingBeans.size() > 1) {
        
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(type, matchingBeans);
					}
					else {
						// In case of an optional Collection/Map, silently ignore a non-unique case:
						// possibly it was meant to be an empty collection of multiple regular beans
						// (before 4.3 in particular when we didn't even look for collection beans).
						return null;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
				// We have exactly one match.
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			return (instanceCandidate instanceof Class ?
					descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}



protected Map<String, Object> findAutowireCandidates( String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
		//從IOC容器中獲取全部的符合類型的BeanName,存入候選數組
		String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
				this, requiredType, true, descriptor.isEager());
		Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
		for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
			if (autowiringType.isAssignableFrom(requiredType)) {
				Object autowiringValue = this.resolvableDependencies.get(autowiringType);
				autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
				if (requiredType.isInstance(autowiringValue)) {
					result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
					break;
				}
			}
		}
		for (String candidate : candidateNames) {
      // 不能是自身,不然會無限注入
			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {			 // end :裏面會調用 getBean() 方法實例化bean ,以 beanName爲key, bean 爲value,存進result中
				addCandidateEntry(result, candidate, descriptor, requiredType);
			}
		}
		if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
			// Consider fallback matches if the first pass failed to find anything...
			DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
			for (String candidate : candidateNames) {
				if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
					addCandidateEntry(result, candidate, descriptor, requiredType);
				}
			}
			if (result.isEmpty()) {
				// Consider self references as a final pass...
				// but in the case of a dependency collection, not the very same bean itself.
				for (String candidate : candidateNames) {
					if (isSelfReference(beanName, candidate) &&
							(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
							isAutowireCandidate(candidate, fallbackDescriptor)) {
						addCandidateEntry(result, candidate, descriptor, requiredType);
					}
				}
			}
		}
		return result;
	}
複製代碼

參考: 圖片借鑑

autoWire部分參考

《Spring源碼深刻解析》

相關文章
相關標籤/搜索