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物件
-
如果bean有factory-method,就用factory-method初始化bean
-
如果物件已經被建立過(比如這個物件是prototype型別的),工廠裡就會儲存有建立過的建構函式和引數,可以直接根據快取的建構函式和引數
-
無參建構函式instantiateBean建立被BeanWrapper包裹的bean
-
有參建構函式autowireConstructor
-
-
如果是第一次初始化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