1. 程式人生 > 其它 >spring使用建構函式初始化bean

spring使用建構函式初始化bean

Spring使用建構函式初始化bean

把所有準備初始化的bean準備好

1.bean初始化的時機

Bean初始化是從AnnotationConfigApplicationContext的refresh()函式呼叫的時候開始。

annotationConfigApplicationContext.refresh();

2.開始對bean進行初始化

AbstractApplicationContext.finishBeanFactoryInitialization中執行到beanFactory.preInstantiateSingletons();

3.preInstantiateSingletons()方法預設是使用DefaultListableBeanFactory的,這個方法裡面把所有掃描出來的beanName拿出來,然後開始初始化所有非靜態、單例、非懶載入的bean,主要就是看getBean()方法

下面程式碼的重點是

  • 拿出掃描出來的所有beanName
  • 將非抽象、非單例、非懶載入的bean進行初始化
	//準備實現單例
	@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}
		// 1.建立beanDefinitionNames的副本beanNames用於後續的遍歷,以允許init等方法註冊新的bean定義
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		//觸發所有非延遲載入單例beans的初始化,主要步驟為呼叫getBean
		for (String beanName : beanNames) {
			//合併父類的bd,在xml配置中用
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//如果不是抽象 && 是單例 && 不是懶載入的
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					//判斷是不是FactoryBean
					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);
						}
					}
				}
                //我們的普通類都是走這裡
				else {
					getBean(beanName);
				}
			}
		}
		// Trigger post-initialization callback for all applicable beans...
		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()裡面呼叫dogetBean()方法,這裡就是正式 開始初始化

呼叫鏈是:

doGetBean方法(bean真正建立地方)

先建立一個空白的bean物件,

然後

	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) {
			/**
			 * 建立 bean 例項,並將例項包裹在 BeanWrapper 實現類物件中返回。
			 * createBeanInstance中包含三種建立 bean 例項的方式:
			 *   1. 通過工廠方法建立 bean 例項
			 *   2. 通過構造方法自動注入(autowire by constructor)的方式建立 bean 例項
			 *   3. 通過無參構造方法方法建立 bean 例項
			 *
			 * 若 bean 的配置資訊中配置了 lookup-method 和 replace-method,則會使用 CGLIB
			 * 增強 bean 例項。關於lookup-method和replace-method後面再說。
			 */
			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;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		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");
			}
			//把bean從DefaultSingletonBeanRegistry.earlySingletonObjects中移除
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		//這是時候還是原生的bean物件
		Object exposedObject = bean;
		try {
			//設定屬性,非常重要
			populateBean(beanName, mbd, instanceWrapper);
			//執行後置處理器,aop就是在這裡完成的處理!!!
			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.createBeanInstance建立一個空的bean物件

  1. 如果bean有factory-method,就用factory-method初始化bean

  2. 如果物件已經被建立過(比如這個物件是prototype型別的),工廠裡就會儲存有建立過的建構函式和引數,可以直接根據快取的建構函式和引數

    • 無參建構函式instantiateBean建立被BeanWrapper包裹的bean

    • 有參建構函式autowireConstructor

  3. 如果是第一次初始化bean,由後置處理器決定要用哪些構造方法

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

		/**
		 * 檢測一個類的訪問許可權spring預設情況下對於非public的類是允許訪問的。
		 */
		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		//跳過
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		/**
		 *
		 * 如果工廠方法不為空,則通過工廠方法構建 bean 物件
		 * 這種構建 bean 的方式可以自己寫個demo去試試
		 * 原始碼就不做深入分析了,有興趣的同學可以和我私下討論
		 */
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		/**
		 * 從spring的原始註釋可以知道這個是一個Shortcut,什麼意思呢?
		 * 當多次構建同一個 bean 時,可以使用這個Shortcut,
		 * 也就是說不在需要次推斷應該使用哪種方式構造bean
		 *  比如在多次構建同一個prototype型別的 bean 時,就可以走此處的hortcut
		 * 這裡的 resolved 和 mbd.constructorArgumentsResolved 將會在 bean 第一次例項
		 * 化的過程中被設定,後面來證明
		 */
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				//如果bd是由factoryMethod建立
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					//如果已經解析了構造方法的引數,則必須要通過一個帶參構造方法來例項
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		//如果是factoryMethod建立的方法
		if (resolved) {
			if (autowireNecessary) {
				//有參
				// 通過構造方法自動裝配的方式構造 bean 物件
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				//通過預設的無參構造方法進行
				return instantiateBean(beanName, mbd);
			}
		}

		/**
		 * 下面的邏輯是,如果只有預設的無參構造方法,ctors是null 直接使用預設的無參構造方法進行初始化
		 * 如果有有參構造方法,
		 */
		// Candidate constructors for autowiring?
		//由後置處理器決定返回哪些構造方法
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		//getResolvedAutowireMode()獲取spring自動裝配的模型
		/**
		 * spring 自動裝配的模型 != 自動裝配的技術
		 * 比如這裡,getResolvedAutowireMode()返回0,AUTOWIRE_NO,預設是通過型別自動裝配
		 * 但是和byType不是一回事
		 *
		 */
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// Preferred constructors for default construction?
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// No special handling: simply use no-arg constructor.
		//使用預設的無參構造方法進行初始化
		return instantiateBean(beanName, mbd);
	}

2.通過後置處理器的determineConstructorsFromBeanPostProcessors方法決定使用哪些建構函式

AutowiredAnnotationBeanPostProcessor後置處理器通過determineCandidateConstructors方法決定使用哪些構造方法

candidateConstructors --最終要返回的建構函式,如果快取中有就直接返回
candidates --最終適用的建構函式
requiredConstructor --帶有required=true的建構函式
defaultConstructor --預設建構函式

先遍歷一遍遍歷所有的建構函式

1.如果當前建構函式有註解

a.requiredConstructor不為空,說明前面已經存在過一個requred=true的建構函式,拋異常

b.當前建構函式是required=true的,判斷candidates是否為空,為空的話說明前面已經有過加註解的建構函式,拋異常

c.前面過濾條件都滿足,將當前requird=true的建構函式賦值給requiredConstructor

d.前面沒有帶註解的建構函式,或者當前建構函式required=true條件滿足,將當前建構函式加入candidates

e.如果加了註解的建構函式中沒有required=true的建構函式,將無參建構函式加入到candidateConstructors

2.如果當前建構函式沒有註解並且引數是0個,將當前的無參建構函式賦值給defaultConstructor

a.在建構函式只有一個且有參時,將此唯一有參建構函式加入candidates

b.在建構函式有兩個的時候,並且存在無參建構函式,將defaultConstructor(上面的無參建構函式)加入candidates

c.在構造器數量大於兩個,並且存在無參構造器的情況下,將返回一個空的candidateConstructors集合,也就是沒有找到構造器。

1.在沒有@Autowired註解的情況下:

無參構造器將直接加入defaultConstructor集合中。

在構造器數量只有一個且有引數時,此唯一有參構造器將加入candidateConstructors集合中。 在構造器數量有兩個的時候,並且存在無參構造器,將defaultConstructor(第一條的無參構造器)放入candidateConstructors集合中。 在構造器數量大於兩個,並且存在無參構造器的情況下,將返回一個空的candidateConstructors集合,也就是沒有找到構造器。

2.在有@Autowired註解的情況下:

判斷required屬性:

true:

先判斷requiredConstructor集合是否為空,若不為空則代表之前已經有一個required=true的構造器了,兩個true將丟擲異常,再判斷candidates集合是否為空,若不為空則表示之前已經有一個打了註解的構造器,此時required又是true,丟擲異常。若兩者都為空將放入requiredConstructor集合中,再放入candidates集合中。

false:

直接放入candidates集合中。 判斷requiredConstructor集合是否為空(是否存在required=true的構造器),若沒有,將預設構造器也放入candidates集合中。 最後將上述candidates賦值給最終返回的candidateConstructors集合。

	@Override
	@Nullable
	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
			throws BeanCreationException {

		// Let's check for lookup methods here...
		if (!this.lookupMethodsChecked.contains(beanName)) {
			try {
				ReflectionUtils.doWithMethods(beanClass, method -> {
					Lookup lookup = method.getAnnotation(Lookup.class);
					if (lookup != null) {
						Assert.state(this.beanFactory != null, "No BeanFactory available");
						LookupOverride override = new LookupOverride(method, lookup.value());
						try {
							RootBeanDefinition mbd = (RootBeanDefinition)
									this.beanFactory.getMergedBeanDefinition(beanName);
							mbd.getMethodOverrides().addOverride(override);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(beanName,
									"Cannot apply @Lookup to beans without corresponding bean definition");
						}
					}
				});
			}
			catch (IllegalStateException ex) {
				throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
			}
			this.lookupMethodsChecked.add(beanName);
		}

		// Quick check on the concurrent map first, with minimal locking.
		//從構造方法的快取當中去拿一個
		Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
		//如果快取中沒有
		if (candidateConstructors == null) {
			// Fully synchronized resolution now...
			synchronized (this.candidateConstructorsCache) {
				candidateConstructors = this.candidateConstructorsCache.get(beanClass);
				//雙重判斷,避免多執行緒併發問題
				if (candidateConstructors == null) {
					Constructor<?>[] rawCandidates;
					try {
						//獲取所有的建構函式
						rawCandidates = beanClass.getDeclaredConstructors();
					}
					catch (Throwable ex) {
						throw new BeanCreationException(beanName,
								"Resolution of declared constructors on bean Class [" + beanClass.getName() +
								"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
					}
					//最終適用的構造器集合(加了註解的)
					List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
					//存放依賴注入的required=true的構造器
					Constructor<?> requiredConstructor = null;
					//存放預設構造器
					Constructor<?> defaultConstructor = null;
					//根據前面primaryConstructor 表示kotlin形式,,不管是什麼構造方法,先執行init{初始化邏輯},後執行構造方法
					Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
					int nonSyntheticConstructors = 0;
					//迴圈拿出來的所有構造方法
					for (Constructor<?> candidate : rawCandidates) {
						if (!candidate.isSynthetic()) {
							nonSyntheticConstructors++;
						}
						else if (primaryConstructor != null) {
							continue;
						}
						//查詢當前構造器上的@AutoWired @Value註解
						AnnotationAttributes ann = findAutowiredAnnotation(candidate);
						//如果沒有註解,再看看父類的註解
						if (ann == null) {
							Class<?> userClass = ClassUtils.getUserClass(beanClass);
							if (userClass != beanClass) {
								try {
									Constructor<?> superCtor =
											//根據當前遍歷的建構函式,獲取建構函式資訊
											userClass.getDeclaredConstructor(candidate.getParameterTypes());
									ann = findAutowiredAnnotation(superCtor);
								}
								catch (NoSuchMethodException ex) {
									// Simply proceed, no equivalent superclass constructor found...
								}
							}
						}
						/**
						 * 1.如果當前建構函式有註解,
						 *   a.requiredConstructor不為空,說明前面已經存在過一個requred=true的建構函式,拋異常(就是不能存在兩個required=true或者 一個required=true和一個required=false)
						 * 	 b.當前建構函式是required=true的,判斷candidates是否為空,為空的話說明前面已經有過加註解的建構函式,拋異常
						 * 	 c.前面過濾條件都滿足,將當前requird=true的建構函式賦值給requiredConstructor
						 * 	 d.前面沒有帶註解的建構函式,或者當前建構函式required=true條件滿足,將當前建構函式加入candidates
						 * 2.如果當前建構函式沒有註解並且引數是0個,將當前的無參建構函式賦值給defaultConstructor
						 */
						//若有註解
						if (ann != null) {
							//已經存在一個required=true的構造器了,丟擲異常,一個類只允許一個帶有required=true註解的建構函式
							if (requiredConstructor != null) {
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
							}
							//判斷此註解上的required屬性
							boolean required = determineRequiredStatus(ann);
							if (required) {
								if (!candidates.isEmpty()) {
									throw new BeanCreationException(beanName,
											"Invalid autowire-marked constructors: " + candidates +
											". Found constructor with 'required' Autowired annotation: " +
											candidate);
								}
								requiredConstructor = candidate;
							}
							//如果當前建構函式加了註解,就會先放到candidates當中,就是@AutoWired(requred=false)或者@AutoWired(required=true)都會加入進去
							candidates.add(candidate);
						}
						//若沒有註解,再判斷建構函式上的引數個數是否為0
						//當某個建構函式的引數是0個,也就是無參建構函式,賦值給defaultConstructor
						else if (candidate.getParameterCount() == 0) {
							defaultConstructor = candidate;
						}
					}
					/**
					 * 將所有加了@AutoWired
					 *
					 */
					//===任一建構函式有註解的情況
					//建構函式頭上有註解(此建構函式有註解),candidates放的是有註解的情況
					//這裡最終的邏輯是,如果有requried=true的建構函式,返回requried = true的建構函式,如果沒有required=true的函式,有無參建構函式,返回無參建構函式
					if (!candidates.isEmpty()) {
						// Add default constructor to list of optional constructors, as fallback.
						//若沒有required=true的構造器
						if (requiredConstructor == null) {
							if (defaultConstructor != null) {
								//將defaultConstructor集合的構造器加入適用構造器集合
								candidates.add(defaultConstructor);
							}
							//建構函式有註解,但是不是requred=true註解
							else if (candidates.size() == 1 && logger.isInfoEnabled()) {
								logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
										"': single autowire-marked constructor flagged as optional - " +
										"this constructor is effectively required since there is no " +
										"default constructor to fall back to: " + candidates.get(0));
							}
						}
						//將適用構造器集合賦值給將要返回的構造器集合
						//如果有required=true的建構函式直接加入,或者沒有required=true,有預設建構函式
						candidateConstructors = candidates.toArray(new Constructor<?>[0]);
					}
					//===剩下的是沒有註解的情況
					//如果bean的建構函式只有一個,並且這個建構函式的引數大於0
					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
						candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
					}
					//當bean的建構函式有兩個 &&  提供了主要的建構函式 && 預設建構函式不為空 && 主要建構函式不等於預設構造方法
					else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
							defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
					}
					//構造
					else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor};
					}
					else {
						//上述條件都不符合的話,返回空集合
						candidateConstructors = new Constructor<?>[0];
					}
					//放入快取,方便下一次呼叫
					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
				}
			}
		}
		return (candidateConstructors.length > 0 ? candidateConstructors : null);
	}

3.autowireConstructor方法上文篩選的建構函式例項化一個物件

	/**
	 * "autowire constructor" (with constructor arguments by type) behavior.
	 * Also applied if explicit constructor argument values are specified,
	 * matching all remaining arguments with beans from the bean factory.
	 * <p>This corresponds to constructor injection: In this mode, a Spring
	 * bean factory is able to host components that expect constructor-based
	 * dependency resolution.
	 * @param beanName the name of the bean
	 * @param mbd the merged bean definition for the bean
	 * @param chosenCtors chosen candidate constructors (or {@code null} if none)
	 * @param explicitArgs argument values passed in programmatically via the getBean method,
	 * or {@code null} if none (-> use constructor argument values from bean definition)
	 * @return a BeanWrapper for the new instance
	 */
	/**
	 * 我們要通過建構函式反射一個類,就需要
	 * Constructor 建構函式
	 * parameterType 引數型別
	 * parameterValue 引數值
	 */
	public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
			@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
		//例項一個BeanWrapperImpl 物件很好理解
		//前面外部返回的BeanWrapper 其實就是這個BeanWrapperImpl
		//因為BeanWrapper是個介面
		BeanWrapperImpl bw = new BeanWrapperImpl();//BeanWrapperImpl有一個WrapperObject的屬性,用來存放真是物件,執行到這裡的時候還沒有被new出來
		//初始化父類的值,沒有什麼大的看頭
		this.beanFactory.initBeanWrapper(bw);

		//這個變數定義你要使用哪個構造方法初始化物件
		Constructor<?> constructorToUse = null;
		//上面那行的構造方法需要哪些引數,
		ArgumentsHolder argsHolderToUse = null;
		Object[] argsToUse = null;

		//確定引數值列表
		//argsToUse可以有兩種辦法設定
		//第一種通過beanDefinition設定,mybatis通過setArugmentCounstructValues
		//第二種通過xml設定
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			//
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
				//獲取已解析的構造方法
				//一般不會有,因為構造方法一般會提供一個
				//除非有多個。那麼才會存在已經解析完成的構造方法
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached constructor...
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			//argsToResolve 引數解析器
			if (argsToResolve != null) {
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
			}
		}
		//如果不存在已解析的構造方法或者 需要的引數
		if (constructorToUse == null || argsToUse == null) {
			// Take specified constructors, if any.
			//如果沒有已經解析的構造方法
			//則需要去解析構造方法
			// Need to resolve the constructor.
			//判斷構造方法是否為空,判斷是否根據構造方法自動注入
			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;
				}
			}

			// Need to resolve the constructor.
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;

			//定義了最小引數個數
			//如果你給構造方法的引數列表給定了具體的值
			//那麼這些值得個數就是構造方法引數的個數
			int minNrOfArgs;
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				//例項一個物件,用來存放構造方法的引數值
				//當中主要存放了引數值和引數值所對應的下表
				//獲得的是通過mbd.getConstructorArgumentValues().addGenericArgumentValue("com.xliyun.spring.springioc.dao.IndexDao");設定的建構函式必須有的引數型別
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				//ConstrucorArgumentValues是存放構造方法的值的,有兩種資料結構list(無序的引數) map(有序的引數)
				//xml配置的bean裡面建構函式<construct-arg index="0" value=""></construct-arg>
				resolvedValues = new ConstructorArgumentValues();
				/**
				 * 確定構造方法引數數量,假設有如下配置:
				 *     <bean id="luban" class="com.luban.Luban">
				 *         <constructor-arg index="0" value="str1"/>
				 *         <constructor-arg index="1" value="1"/>
				 *         <constructor-arg index="2" value="str2"/>
				 *     </bean>
				 *
				 *     在通過spring內部給了一個值得情況那麼表示你的構造方法的最小引數個數一定
				 *
				 * minNrOfArgs = 3
				 */
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}

			//根據構造方法的訪問許可權級別和引數數量進行排序
			//怎麼排序的呢?
			/**
			 *  有限反問許可權,繼而引數個數
			 *  這個自己可以寫個測試去看看到底是不是和我說的一樣
			 * 1. public Luban(Object o1, Object o2, Object o3)
			 * 2. public Luban(Object o1, Object o2)
			 * 3. public Luban(Object o1)
			 * 4. protected Luban(Integer i, Object o1, Object o2, Object o3)
			 * 5. protected Luban(Integer i, Object o1, Object o2)
			 * 6. protected Luban(Integer i, Object o1)
			 */
			AutowireUtils.sortConstructors(candidates);
			//定義了一個差異變數,這個變數很有分量,後面有註釋
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set<Constructor<?>> ambiguousConstructors = null;
			LinkedList<UnsatisfiedDependencyException> causes = null;

			//迴圈所有的構造方法
			for (Constructor<?> candidate : candidates) {
				Class<?>[] paramTypes = candidate.getParameterTypes();

				/**
				 * 這個判斷別看只有一行程式碼理解起來很費勁
				 * 首先constructorToUse != null這個很好理解,e
				 * 前面已經說過首先constructorToUse主要是用來裝已經解析過了並且在使用的構造方法
				 * 只有在他等於空的情況下,才有繼續的意義,因為下面如果解析到了一個符合的構造方法
				 * 就會賦值給這個變數(下面註釋有寫)。故而如果這個變數不等於null就不需要再進行解析了,說明spring已經
				 * 找到一個合適的構造方法,直接使用便可以
				 * argsToUse.length > paramTypes.length這個程式碼就相當複雜了
				 * 首先假設 argsToUse = [1,"luban",obj]
				 * 那麼回去匹配到上面的構造方法的1和5
				 * 由於構造方法1有更高的訪問許可權,所有選擇1,儘管5看起來更加匹配
				 * 但是我們看2,直接引數個數就不對所以直接忽略
				 *
				 *
				 */
				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 {
						//判斷是否加了ConstructorProperties註解如果加了則把值取出來
						//可以寫個程式碼測試一下
						//@ConstructorProperties(value = {"xxx", "111"})
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
						if (paramNames == null) {
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								//獲取構造方法引數名稱列表
								/**
								 * 假設你有一個(String xiaoliyu,Object zilu)
								 * 則paramNames=[luban,xiaoliyu]
								 */
								paramNames = pnd.getParameterNames(candidate);
							}
						}
						//獲取構造方法引數值列表
						/**
						 * 這個方法比較複雜
						 * 因為spring只能提供字串的引數值,比如我們配置
						 * paramNames是引數的名字
						 *                  <bean id="luban" class="com.luban.Luban">
						 * 				          <constructor-arg index="0" value="另一個bean的id,但是填在這裡的是字串,需要通過createArgumentArray轉換"/>
						 * 				     </bean>
						 * 				     或者
						 * 				     public void indexDao(String xiaoliyu)
						 * 故而需要進行轉換
						 * argsHolder所包含的值就是xiaoliyun轉換之後的物件
						 */
						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);
				}

				/**
				 * typeDiffWeight 差異量,何謂差異量呢?
				 * argsHolder.arguments和paramTypes之間的差異
				 * 每個引數值得型別與構造方法引數列表的型別直接的差異
				 * 通過這個差異量來衡量或者確定一個合適的構造方法
				 *
				 * 值得注意的是constructorToUse=candidate
				 *
				 * 第一次迴圈一定會typeDiffWeight < minTypeDiffWeight,因為minTypeDiffWeight的值非常大
				 * 然後每次迴圈會把typeDiffWeight賦值給minTypeDiffWeight(minTypeDiffWeight = typeDiffWeight)
				 * else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight)
				 * 第一次迴圈肯定不會進入這個
				 * 第二次如果進入了這個分支代表什麼?
				 * 代表有兩個構造方法都符合我們要求?那麼spring有迷茫了(spring經常在迷茫)
				 * spring迷茫了怎麼辦?
				 * ambiguousConstructors.add(candidate);
				 * 顧名思義。。。。
				 * ambiguousConstructors=null 非常重要?
				 * 為什麼重要,因為需要清空
				 * 這也解釋了為什麼他找到兩個符合要求的方法不直接拋異常的原因
				 * 如果這個ambiguousConstructors一直存在,spring會在迴圈外面去exception
				 * 很牛逼呀!!!!
				 */
				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;//最小引數 -1024
					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)");
			}

			//如果ambiguousConstructors還存在則異常?為什麼會在上面方法中直接exception?
			//上面註釋當中有說明
			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) {
				/*
				 * 快取相關資訊,比如:
				 *   1. 已解析出的構造方法物件 resolvedConstructorOrFactoryMethod
				 *   2. 構造方法引數列表是否已解析標誌 constructorArgumentsResolved
				 *   3. 引數值列表 resolvedConstructorArguments 或 preparedConstructorArguments
				 *   這些資訊可用在其他地方,用於進行快捷判斷
				 */
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}

		Assert.state(argsToUse != null, "Unresolved constructor arguments");
		//instantiate()生成bean
		bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
		return bw;
	}

4.建構函式例項化物件時的引數如何例項化

呼叫鏈AbstarctAutowireCpableBeanFactory.createBeanInstance ==> autowireConstructor ==> ConstructorResorlver.autowireConstructor

假如最終適用的建構函式是有引數的建構函式,然後第一次初始化的時候呼叫

argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
								getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);

populateBean為物件屬性賦值

AbstarctAutowireCpableBeanFactory.createBeanInstance ==> populateBean

spring是如何解決迴圈依賴問題

簡單總結版:

1.獲取A類時,一級快取singletonObjects獲取不到,並且正在建立set(singletonsCurrentlyInCreation)中沒有A類

2.從二級快取(earlySingletonObjects)中獲取,還是沒有

3.二級工廠singletonFactories存放的都是繼承了ObjectFactory的物件,有個getObject方法,通過lambda執行呼叫

2.通過createBean() -->docreateBean()建立類(選擇哪個建構函式的程式碼在這)

DefaultSingletonBeanRegistry有三個快取map

	/** Cache of singleton objects: bean name to bean instance. */
	//用於存放完全初始化好的 bean從該快取中取出的 bean可以直接使用 一級快取
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name to ObjectFactory. */
	//存放 bean工廠物件解決迴圈依賴 三級快取
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
	//存放原始的bean物件用於解決迴圈依賴,注意:存到裡面的物件還沒有被填充屬性 二級快取
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

假如A類有成員變數B b;B類有成員變數A a,屬於迴圈依賴的情況

1.A類建立bean的時候呼叫getBean(a) --> doCreateBean(a) --> populateBean(b) --> resolveDependency(b) --> doResovleDependency(b) --> resovleCandidate(b) --> getBean(b)

2.A類在呼叫getBean(a)方法的時候就通過DefaultSingletonBeanRegistry.getSingleton(a)將a

3.A類在doCreateBean(a)的時候就加入到singletonFactories

4.B類被A類依賴,開始初始化getBean(b) --> doCreateBean(b) --> populateBean(a) --> resolveDependency(a) --> doResovleDependency(a) --> resovleCandidate() --> getBean(a)

AbstractBeanFactory.doGetBean(a)中開始初始化A類

1.當A類開始初始化bean執行AbstranctBeanFactory.doGetBean(a),並第一次呼叫AbstractBeanFactory.getBean(a) --> DefaultSingletonBeanRegistry.getSingleton(String beanName, boolean allowEarlyReference) singletonObjects沒有A,並且isSingletonCurrentlyInCreation(beanName)也是false,所以返回null

DefaultSingletonBeanRegistry.protected Object getSingleton(String beanName, boolean allowEarlyReference)

	/**
	 * Return the (raw) singleton object registered under the given name.
	 * <p>Checks already instantiated singletons and also allows for an early
	 * reference to a currently created singleton (resolving a circular reference).
	 * @param beanName the name of the bean to look for
	 * @param allowEarlyReference whether early references should be created or not
	 * @return the registered singleton object, or {@code null} if none found
	 */
	//本方法主要用來處理迴圈依賴
	/**
	 * allowEarlyReference引數的含義是Spring是否允許迴圈依賴,預設為true
	 * 所以當allowEarlyReference設定為false的時候,當專案存在迴圈依賴,會啟動失敗
	 */
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		//從map中獲取bean如果不為空直接返回,不再進行初始化工作
		//本方法主要用於程式設計師在外部使用annotationConfigApplicationContext.getBean()的時候使用
		/**
		 * 1.按照程式碼的邏輯,我們第一次呼叫到這裡的時候,記錄正在建立的bean的set裡面是空的,所以isSingletonCurrentlyInCreation(beanName)返回false
		 * 所以本次getSingleton返回null
		 * 2.第二次呼叫的是下面的getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法
		 * spring已經做了該做的驗證,如果為空則建立物件
		 */
		Object singletonObject = this.singletonObjects.get(beanName);
		//如果從singletonObjects取不到bean,並且正在建立當中
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

2.然後doGetBean中判斷返回的sharedInstance為null,執行DefaultSingletonBeanRegistry.getSingleton(String beanName, ObjectFactory<?> singletonFactory),注意兩個getsingleton引數不一樣。這時A的beanName通過beforeSingletonCreation(beanName);被放入singletonsCurrentlyInCreation這個set

	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 + "'");
				}
				/**
				 * 將beanName新增到singletonsCurrentlyInCreation這樣一個集合中
				 * 表示beanName對應的bean正在建立中
				 */
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					//在這裡建立bean 這裡下一步是呼叫的是lambda表示式return createBean(beanName, mbd, args);
					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;
		}
	}

3.繼續執行doGetBean() --> AbstractAutowireCapableBeanFactory.createBean() --> AbstractAutowireCapableBeanFactory.doCreateBean()

在doCreateBean()當中通過createBeanInstance()方法反射建立物件

然後在isSingletonCurrentlyInCreation(beanName)方法中判斷當前beanName是否被加到singletonsCurrentlyInCreation這個set當中,剛才第2步已經新增完了

	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) {
			/**
			 * 建立 bean 例項,並將例項包裹在 BeanWrapper 實現類物件中返回。
			 * createBeanInstance中包含三種建立 bean 例項的方式:
			 *   1. 通過工廠方法建立 bean 例項
			 *   2. 通過構造方法自動注入(autowire by constructor)的方式建立 bean 例項
			 *   3. 通過無參構造方法方法建立 bean 例項
			 *
			 * 若 bean 的配置資訊中配置了 lookup-method 和 replace-method,則會使用 CGLIB
			 * 增強 bean 例項。關於lookup-method和replace-method後面再說。
			 */
			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;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		//判斷
		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");
			}
			//把bean從DefaultSingletonBeanRegistry.earlySingletonObjects中移除
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		//這是時候還是原生的bean物件
		Object exposedObject = bean;
		try {
			//設定屬性,非常重要
			populateBean(beanName, mbd, instanceWrapper);
			//執行後置處理器,aop就是在這裡完成的處理!!!
			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;
	}

4.往三級快取singletonFactories新增beanName資料,並移除二級快取earlySingletonObjects中的beanName

	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				this.singletonFactories.put(beanName, singletonFactory);
				//把bean從earlySingletonObjects移除
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

ObjectFactory是一個介面,只有一個方法getObject ,符合lambda表示式的,下面的程式碼就是實現這個介面,實際上是呼叫@EnableAspectJAutoProxy註解匯入的AnnotationAwareAspectJAutoProxyCreator。可以直接理解為返回了一個A的物件

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

5.生成物件以後通過AbstractAutowireCapableBeanFactory.populateBean填充物件屬性

我們從populateBean()方法的autowireByType()方法去看。這時候需要填充A的屬性,發現需要B類,呼叫DefaultLisatableBeanFactory.resolveDependency(b) --> getBean(b)初始化B類

6.當B類填充屬性A時,再次呼叫getSingleton(String beanName, boolean allowEarlyReference)

這一次呼叫getSingleton邏輯就不一樣了,singletonObject一級快取中還是獲取不到,二級快取earlySingletonObjects也獲取不到,然後從三級快取中能獲取到上面第4步放到singletonFactories中的未完全初始化的a物件。

刪除三級快取的資料,將a物件放到二級快取,返回a物件

	//本方法主要用來處理迴圈依賴
	/**
	 * allowEarlyReference引數的含義是Spring是否允許迴圈依賴,預設為true
	 * 所以當allowEarlyReference設定為false的時候,當專案存在迴圈依賴,會啟動失敗
	 */
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		//從map中獲取bean如果不為空直接返回,不再進行初始化工作
		//本方法主要用於程式設計師在外部使用annotationConfigApplicationContext.getBean()的時候使用
		/**
		 * 1.按照程式碼的邏輯,我們第一次呼叫到這裡的時候,記錄正在建立的bean的set裡面是空的,所以isSingletonCurrentlyInCreation(beanName)返回false
		 * 所以本次getSingleton返回null
		 * 2.第二次呼叫的是下面的getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法
		 * spring已經做了該做的驗證,如果為空則建立物件
		 */
		Object singletonObject = this.singletonObjects.get(beanName);
		//如果從singletonObjects取不到bean,並且正在建立當中
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

https://www.jianshu.com/p/16a44c25c9d9

https://javazhiyin.blog.csdn.net/article/details/107602783

通俗易懂的三級快取解釋迴圈依賴https://blog.csdn.net/f641385712/article/details/92801300