概述
前文中介紹的finishBeanFactoryInitialization方法是IOC的核心涂臣,其中的getBean方法還沒有講解到,在這里繼續(xù)展開解析。我們閱讀源碼時(shí)流炕,要抓主次,先按主線下來仅胞,然后在主線里做支路的標(biāo)記每辟,等主線閱讀完后,再回顧支路的標(biāo)記慢慢進(jìn)去展開干旧,這樣避免引起“"迷路現(xiàn)象"渠欺,在源碼中兜轉(zhuǎn)一回不明白所以然。
在前文中椎眯,我們主要關(guān)注的是finishBeanFactoryInitialization里的preInstantiateSingletons方法挠将,實(shí)例化所有剩余的非懶加載單例 bean,那如何實(shí)例化的呢编整?這得用到getBean這個(gè)方法舔稀。
getBean
AbstractBeanFactory類中的getBean方法,這里邊有好幾個(gè)getBean方法,我們主要看第一個(gè)用到的掌测,源碼如下:
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
doGetBean是主要做事的方法,那么多getBean方法只是給外部提供一個(gè)調(diào)用接口,查看doGetBean的源碼:
/**
* Return an instance, which may be shared or independent, of the specified bean.
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//注釋1. 獲取 bean 名稱内贮,如果需要,去掉引用前綴(例如修飾符)赏半,還有將別名轉(zhuǎn)換成最終 beanName
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 注釋2. 檢查緩存中或者實(shí)例工廠是否有對(duì)應(yīng)的實(shí)例或者從 singletonFactories 中的 ObjectFactory 中獲取
Object sharedInstance = getSingleton(beanName);
// 注釋3. 如果緩存中存在該beanName的實(shí)例
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 + "'");
}
}
// 注釋3-1. 返回對(duì)應(yīng)的實(shí)例贺归,普通的bean返回
// 對(duì) FactoryBean 的特殊處理,是返回指定方法返回的實(shí)例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 注釋4. 如果緩存中不存在該beanName的實(shí)例
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 注釋4-1. 循環(huán)依賴校驗(yàn),假設(shè)我們?cè)谝粋€(gè)循環(huán)引用中断箫,我們之前已經(jīng)創(chuàng)建了這個(gè)bean實(shí)例拂酣,則會(huì)拋出錯(cuò)誤:循環(huán)依賴
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 注釋4-2. 獲取parentBeanFactory
BeanFactory parentBeanFactory = getParentBeanFactory();
// 注釋4-2-1. 如果parentBeanFactory存在衅斩,并且beanName在當(dāng)前BeanFactory不存在Bean定義光督,則嘗試從parentBeanFactory中獲取bean實(shí)例
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.將別名解析成真正的beanName
String nameToLookup = originalBeanName(name);
//通過parentBeanFactory獲取bean實(shí)例
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);
}
}
// 注釋4-2-2. 如果不是僅僅做類型檢查則是創(chuàng)建 bean,這里要將beanName放到alreadyCreated緩存
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 注釋5. 根據(jù)beanName重新獲取MergedBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 檢查MergedBeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 注釋6. 保證當(dāng)前 bean 所依賴的bean的實(shí)例化,
String[] dependsOn = mbd.getDependsOn();
// 如果存在依賴則需要遞歸實(shí)例化依賴的 bean
if (dependsOn != null) {
for (String dep : dependsOn) {
// 檢查循環(huán)依賴報(bào)錯(cuò)~
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 將dep和beanName的依賴關(guān)系注冊(cè)到緩存中
registerDependentBean(dep, beanName);
try {
// 獲取dep對(duì)應(yīng)的bean實(shí)例惋耙,如果dep還沒有創(chuàng)建bean實(shí)例,則創(chuàng)建dep的bean實(shí)例
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance. 創(chuàng)建 bean 實(shí)例
// 注釋7. singleton 單例模式(最常使用)
if (mbd.isSingleton()) {
// 注釋7-1. scope為singleton的bean創(chuàng)建
//ObjectFactory為函數(shù)式接口,lambda表達(dá)式重寫了getObject方法
sharedInstance = getSingleton(beanName, () -> {
try {
//注釋7-1-1. 創(chuàng)建Bean實(shí)例
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;
}
});
//注釋7-1-2.返回beanName對(duì)應(yīng)的實(shí)例對(duì)象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//注釋7-2. scope為prototype的bean創(chuàng)建
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
//注釋7-2-1. 創(chuàng)建實(shí)例前的操作
beforePrototypeCreation(beanName);
//注釋7-2-2. 創(chuàng)建Bean實(shí)例
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//注釋7-2-3.創(chuàng)建實(shí)例后的操作
afterPrototypeCreation(beanName);
}
//注釋7-2-4.返回beanName對(duì)應(yīng)的實(shí)例對(duì)象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
//注釋7-3. 其他scope的bean創(chuàng)建
else {
//注釋7-3-1. 獲取scopeName诱渤,根據(jù)scopeName蚌铜,從緩存拿到scope實(shí)例
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 {
//注釋7-3-2. 其他scope的bean創(chuàng)建,新建了一個(gè)ObjectFactory
//ObjectFactory為函數(shù)式接口,lambda表達(dá)式重寫了getObject方法
Object scopedInstance = scope.get(beanName, () -> {
//創(chuàng)建實(shí)例前的操作
beforePrototypeCreation(beanName);
try {
//創(chuàng)建bean實(shí)例
return createBean(beanName, mbd, args);
}
finally {
//創(chuàng)建實(shí)例后的操作
afterPrototypeCreation(beanName);
}
});
//返回beanName對(duì)應(yīng)的實(shí)例對(duì)象
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.
// 檢查需要的類型是否符合 bean 的實(shí)際類型
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
//類型不對(duì),則嘗試轉(zhuǎn)換bean類型
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());
}
}
//返回創(chuàng)建出來的bean實(shí)例對(duì)象
return (T) bean;
}
跟著注釋走一遍饺谬,理解完其執(zhí)行過程后捂刺,進(jìn)入源碼解析。
注釋2.檢查緩存中或者實(shí)例工廠是否有對(duì)應(yīng)的實(shí)例或者從 singletonFactories 中的 ObjectFactory 中獲取募寨。在前文中對(duì)getSingleton這個(gè)方法解析過一次族展,里邊使用了三級(jí)緩存的概念,可以回顧一下拔鹰。
注釋3-1. 返回對(duì)應(yīng)的實(shí)例(見源碼解析1)
注釋4-2 通過parentBeanFactory 獲取bean實(shí)例
注釋4-2-2 判斷如果不是僅僅做類型檢查則是創(chuàng)建 bean仪缸,這里要將beanName放到alreadyCreated緩存(見源碼解析2)
注釋5. 獲取MergedBeanDefinition,參考前文中的getMergedLocalBeanDefinition方法解析
注釋6. 保證當(dāng)前 bean 所依賴的bean的實(shí)例化,isDependent方法來檢查循環(huán)依賴列肢,registerDependentBean方法為記錄beanName所對(duì)應(yīng)的bean和所依賴的ben(dep)之間的依賴關(guān)系恰画,注冊(cè)到緩存中。(見源碼解析3)
注釋7. 按scope不同進(jìn)行創(chuàng)建 bean 實(shí)例
注釋7-1. scope為singleton的bean創(chuàng)建,這里調(diào)用了getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法(見源碼解析4)
注釋7-1-1. 創(chuàng)建Bean實(shí)例,createBean方法(這個(gè)方法很重要瓷马,在下一篇詳細(xì)解析)
注釋7-3-2 創(chuàng)建prototype的bean實(shí)例前的操作beforePrototypeCreation方法拴还、創(chuàng)建實(shí)例后的操作afterPrototypeCreation方法,可以點(diǎn)進(jìn)去跟蹤簡(jiǎn)單了解一下這個(gè)執(zhí)行過程:主要是在進(jìn)行 bean 實(shí)例的創(chuàng)建前,將 beanName 添加到 prototypesCurrentlyInCreation 緩存决采;bean 實(shí)例創(chuàng)建后自沧,將 beanName 從 prototypesCurrentlyInCreation 緩存中移除。這邊 prototypesCurrentlyInCreation 存放的類型為 Object树瞭,在只有一個(gè) beanName 的時(shí)候拇厢,直接存該 beanName,也就是 String 類型晒喷;當(dāng)有多個(gè) beanName 時(shí)孝偎,轉(zhuǎn)成 Set 來存放。
【源碼解析1】 獲取 beanName 對(duì)應(yīng)的實(shí)例對(duì)象:AbstractBeanFactory類中的getObjectForBeanInstance方法:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
// 查看isFactoryDereference可知道凉敲,這里判斷的是 beanName 前綴是否是& 符號(hào)
if (BeanFactoryUtils.isFactoryDereference(name)) {
//如果是NullBean類型衣盾,直接返回
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 如果不是空 bean,又不是工廠 bean爷抓,報(bào)錯(cuò)
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
// 如果beanInstance不是FactoryBean(也就是普通bean)势决,則直接返回beanInstance
// 如果beanInstance是FactoryBean,并且name以“&”為前綴蓝撇,則直接返回beanInstance(以“&”為前綴代表想獲取的是FactoryBean本身)
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// 加載工廠 bean
// 從上面排除信息可以知道果复,這里開始beanInstance是FactoryBean,但name不帶有“&”前綴渤昌,表示想要獲取的是FactoryBean創(chuàng)建的對(duì)象實(shí)例
Object object = null;
if (mbd == null) {
// 如果mbd為空,先從緩存factoryBeanObjectCache中獲取
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
// 到了這一步虽抄,很確定是工廠 bean 類型了,類型強(qiáng)轉(zhuǎn)
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
// mbd為空走搁,但是該bean的BeanDefinition在緩存中存在,則獲取該bean的MergedBeanDefinitio
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
// 判斷mbd 是否是合成的BeanDefinition
boolean synthetic = (mbd != null && mbd.isSynthetic());
//注釋1. 通過 getObjectFromFactoryBean方法獲取對(duì)象實(shí)例
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
FactoryBean 前文中已經(jīng)介紹過其定義了迈窟,是一種特殊的bean即工廠 bean私植,可以自己創(chuàng)建 bean 實(shí)例。
這里主要繼續(xù)解析getObjectFromFactoryBean方法车酣,獲取對(duì)象實(shí)例(見源碼解析1-1)
【源碼解析1-1】 FactoryBeanRegistrySupport類中曲稼,從 FactoryBean 獲取對(duì)象實(shí)例:getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//factoryBean如果是單例,并且已經(jīng)存在于單例對(duì)象緩存中
if (factory.isSingleton() && containsSingleton(beanName)) {
//加鎖操作
synchronized (getSingletonMutex()) {
//獲取緩存
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 注釋1. 緩存不存在,通過factoryBean獲取beanName實(shí)例對(duì)象
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
//獲取緩存
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
//如果該beanName已經(jīng)在緩存中存在骇径,則將object替換成緩存中的alreadyThere
object = alreadyThere;
}
else {
if (shouldPostProcess) {
//該beanName被標(biāo)記了屬于正在創(chuàng)建的bean躯肌,存在于Set singletonsCurrentlyInCreation中
//則直接返回該實(shí)例對(duì)象
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
// 創(chuàng)建單例前的前置操作,校驗(yàn)下存不存在者春,不存在拋異常
beforeSingletonCreation(beanName);
try {
//注釋2. 對(duì)bean實(shí)例進(jìn)行后置處理破衔,執(zhí)行所有已注冊(cè)的BeanPostProcessor的postProcessAfterInitialization方法
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
// 創(chuàng)建單例后的后置操作,校驗(yàn)下存不存在钱烟,不存在拋異常
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
//factoryBean不是單例的情況下晰筛,通過factoryBean獲取beanName實(shí)例對(duì)象
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
// 對(duì)bean實(shí)例進(jìn)行后置處理,執(zhí)行所有已注冊(cè)的BeanPostProcessor的postProcessAfterInitialization方法
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
//返回object實(shí)例對(duì)象
return object;
}
}
這個(gè)方法執(zhí)行流程看下來拴袭,真正做事的得看doGetObjectFromFactoryBean這個(gè)方法读第。
注釋1. 緩存不存在,通過factoryBean獲取beanName實(shí)例對(duì)象,doGetObjectFromFactoryBean(見源碼解析1-2)
注釋2. 對(duì)bean實(shí)例進(jìn)行后置處理,執(zhí)行所有已注冊(cè)的BeanPostProcessor的postProcessAfterInitialization方法,postProcessObjectFromFactoryBean(見源碼解析1-3)
【源碼解析1-2】 通過FactoryBean來獲取到對(duì)象實(shí)例 : doGetObjectFromFactoryBean
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
//系統(tǒng)安全管理驗(yàn)證
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
//調(diào)用FactoryBean的getObject方法獲取bean對(duì)象實(shí)例
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//不作系統(tǒng)安全管理驗(yàn)證拥刻,調(diào)用FactoryBean的getObject方法獲取bean對(duì)象實(shí)例
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
//getObject返回的是空值怜瞒,并且該beanName正在初始化中,則直接拋異常
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
//創(chuàng)建一個(gè)新的NullBean對(duì)象
object = new NullBean();
}
//返回創(chuàng)建好的bean對(duì)象實(shí)例
return object;
}
這里主要就是通過factory bean 的 getObject方法來獲取對(duì)象般哼。
【源碼解析1-3】 子類AbstractAutowireCapableBeanFactory postProcessObjectFromFactoryBean吴汪,重寫了父類FactoryBeanRegistrySupport里的方法:
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
//
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//遍歷所有注冊(cè)的BeanPostProcessor實(shí)現(xiàn)類,調(diào)用postProcessAfterInitialization方法
for (BeanPostProcessor processor : getBeanPostProcessors()) {
//在bean初始化后蒸眠,調(diào)用postProcessAfterInitialization方法
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
//如果返回null漾橙,則直接返回結(jié)果
return result;
}
//有值則直接返回
result = current;
}
return result;
}
我們創(chuàng)建的beanFactory為DefaultListableBeanFactory類型,這邊走的是 AbstractAutowireCapableBeanFactory 里的方法楞卡,它為DefaultListableBeanFactory父類霜运,F(xiàn)actoryBeanRegistrySupport的子類,@Override重寫父類FactoryBeanRegistrySupport的postProcessObjectFromFactoryBean方法蒋腮。
前面的registerBeanPostProcessors已經(jīng)幫我們注冊(cè)了各類BeanPostProcessors淘捡,它會(huì)再bean實(shí)例化后,初始化階段執(zhí)行被執(zhí)行其接口的方法池摧。
【源碼解析2】 將beanName放到alreadyCreated緩存 : markBeanAsCreated方法
protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
synchronized (this.mergedBeanDefinitions) {
//如果alreadyCreated緩存中不包含beanName
if (!this.alreadyCreated.contains(beanName)) {
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
//將beanName的MergedBeanDefinition從mergedBeanDefinitions緩存中移除焦除,在之后重新獲取MergedBeanDefinition
clearMergedBeanDefinition(beanName);
//將beanName添加到alreadyCreated緩存中,代表該beanName的bean實(shí)例已經(jīng)創(chuàng)建(或即將創(chuàng)建)
this.alreadyCreated.add(beanName);
}
}
}
}
alreadyCreated 是一個(gè)Set集合作為已經(jīng)創(chuàng)建(或即將創(chuàng)建)的實(shí)例集合险绘,
這邊會(huì)將 beanName 對(duì)應(yīng)的 MergedBeanDefinition 移除踢京,然后在之后的代碼重新獲取誉碴,主要是為了使用最新的 MergedBeanDefinition 來進(jìn)行創(chuàng)建操作。
【源碼解析3】 保證當(dāng)前 bean 所依賴的bean的實(shí)例化
檢查循環(huán)依賴:來自DefaultSingletonBeanRegistry類中的 isDependent方法
protected boolean isDependent(String beanName, String dependentBeanName) {
synchronized (this.dependentBeanMap) {
return isDependent(beanName, dependentBeanName, null);
}
}
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
// 點(diǎn)開canonicalName方法可以看到將別名解析為真正的名稱
String canonicalName = canonicalName(beanName);
//依賴canonicalName的beanName集合
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
//如果dependentBeans為空瓣距,則兩者必然還未確定依賴關(guān)系黔帕,返回fals
return false;
}
if (dependentBeans.contains(dependentBeanName)) {
//如果dependentBeans包含dependentBeanName,則表示兩者已確定依賴關(guān)系蹈丸,返回true
return true;
}
//循環(huán)檢查成黄,即檢查依賴canonicalName的所有beanName是否存在被dependentBeanName依賴的(即隔層依賴)
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
//已經(jīng)檢查過的添加到alreadySeen,避免重復(fù)檢查
alreadySeen.add(beanName);
//隔層依賴檢查
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
registerDependentBean方法:記錄beanName所對(duì)應(yīng)的bean和所依賴的ben(dep)之間的依賴關(guān)系逻杖,注冊(cè)到緩存中
public void registerDependentBean(String beanName, String dependentBeanName) {
//解析別名
String canonicalName = canonicalName(beanName);
//加鎖操作
synchronized (this.dependentBeanMap) {
//如果依賴關(guān)系還沒有注冊(cè)奋岁,則將兩者的關(guān)系注冊(cè)到dependentBeanMap和dependenciesForBeanMap緩存
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
//加鎖操作
synchronized (this.dependenciesForBeanMap) {
//將canonicalName添加到dependentBeanName依賴的beanName集合中
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
dependenciesForBeanMap:beanName 對(duì)應(yīng)的 bean 依賴的所有 bean 的 beanName 集合,
前面提到的dependentBeanMap 是所有依賴 beanName 對(duì)應(yīng)的 bean 的 beanName 集合
【源碼解析4】 前文介紹過getSingleton(String beanName)方法荸百,這里調(diào)用的是 DefaultSingletonBeanRegistry類中的getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 注釋 全局變量闻伶,加鎖
synchronized (this.singletonObjects) {
// 首先檢查beanName對(duì)應(yīng)的bean實(shí)例是否在緩存中存在
Object singletonObject = this.singletonObjects.get(beanName);
//如果不存在,則進(jìn)入創(chuàng)建操作
if (singletonObject == null) {
//當(dāng)bean factory的單例處于destruction狀態(tài)時(shí),不允許進(jìn)行單例bean創(chuàng)建够话,拋出異常
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-1. 創(chuàng)建單例前的操作蓝翰,校驗(yàn)是否 beanName 是否有別的線程在初始化,并加入初始化狀態(tài)中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 執(zhí)行singletonFactory的getObject方法獲取bean實(shí)例
//實(shí)際執(zhí)行的是 createBean 方法
singletonObject = singletonFactory.getObject();
//標(biāo)記為新的單例對(duì)象
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;
}
//注釋1-2. 創(chuàng)建單例后的操作女嘲,移除初始化狀態(tài)
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 注釋2. 如果是新的單例對(duì)象,加入緩存
//singletonObjects畜份、registeredSingletons
addSingleton(beanName, singletonObject);
}
}
// 返回單例對(duì)象
return singletonObject;
}
}
這個(gè)方法傳入的第二個(gè)參數(shù)為lambda表達(dá)式的匿名函數(shù),ObjectFactory為函數(shù)式接口,所以singletonFactory的getObject方法會(huì)觸發(fā)匿名函數(shù)里的createBean方法欣尼。
注釋1-1爆雹、1-2. 創(chuàng)建單例前的操作、創(chuàng)建單例后的操作愕鼓,出現(xiàn)在創(chuàng)建單例的前后(見源碼解析5)
注釋2. 如果是新的單例對(duì)象钙态,將 beanName 和對(duì)應(yīng)的單例對(duì)象添加到緩存中:addSingleton方法
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 1.添加到單例對(duì)象緩存
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
// 2.將單例工廠緩存移除(已經(jīng)不需要)
this.singletonFactories.remove(beanName);
// 3.將早期單例對(duì)象緩存移除(已經(jīng)不需要)
this.earlySingletonObjects.remove(beanName);
// 4.添加到已經(jīng)注冊(cè)的單例對(duì)象緩存
this.registeredSingletons.add(beanName);
}
}
這個(gè)方法是比較重要的,多關(guān)注一下拒啰,乍一看就是對(duì)各類Map的操作驯绎,前文我們已經(jīng)了解過singletonObjects、earlySingletonObjects谋旦、singletonFactories 構(gòu)成了三級(jí)緩存的概念剩失,這里是把創(chuàng)建好的實(shí)例對(duì)象移動(dòng)到一級(jí)緩存singletonObjects 和注冊(cè)的單例對(duì)象緩存registeredSingletons中,移除掉二級(jí)册着、三級(jí)緩存拴孤。一級(jí)緩存中的是完全態(tài)創(chuàng)建的實(shí)例對(duì)象,二級(jí)甲捏、三級(jí)是創(chuàng)建中的半成品實(shí)例對(duì)象演熟。
【源碼解析5】
protected void beforeSingletonCreation(String beanName) {
// 先校驗(yàn)beanName是否為要在創(chuàng)建檢查排除掉的(inCreationCheckExclusions緩存),如果不是,
// 則將beanName加入到正在創(chuàng)建bean的緩存中(Set)芒粹,如果beanName已經(jīng)存在于該緩存兄纺,會(huì)返回false拋出異常(這種情況出現(xiàn)在構(gòu)造器的循環(huán)依賴)
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
protected void afterSingletonCreation(String beanName) {
// 先校驗(yàn)beanName是否為要在創(chuàng)建檢查排除掉的(inCreationCheckExclusions緩存),如果不是化漆,
// 則將beanName從正在創(chuàng)建bean的緩存中(Set)移除估脆,如果beanName不存在于該緩存,會(huì)返回false拋出異常
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
inCreationCheckExclusions 是要在創(chuàng)建檢查排除掉的 beanName 集合座云,正常為空疙赠,可以不管。這邊主要是引入了 singletonsCurrentlyInCreation 緩存:當(dāng)前正在創(chuàng)建的 bean 的 beanName 集合朦拖。在 beforeSingletonCreation 方法中圃阳,通過添加 beanName 到該緩存,可以預(yù)防出現(xiàn)構(gòu)造器循環(huán)依賴的情況璧帝。
為什么這里無法解決構(gòu)造器循環(huán)依賴捍岳?
我們之前在前文提過,getSingleton 方法是解決循環(huán)引用的核心代碼裸弦。有一句話:“我們先用構(gòu)造函數(shù)創(chuàng)建一個(gè) “不完整” 的 bean 實(shí)例”祟同,從這句話可以看出,構(gòu)造器循環(huán)依賴是無法解決的理疙,因?yàn)楫?dāng)構(gòu)造器出現(xiàn)循環(huán)依賴,我們連 “不完整” 的 bean 實(shí)例都構(gòu)建不出來泞坦。Spring 能解決這類循環(huán)依賴的方案有:通過 setter 注入的循環(huán)依賴窖贤、通過屬性注入的循環(huán)依賴,使用@lazy注解,使用@PostConstruct等贰锁,優(yōu)先建議使用setter注入來解決赃梧。
總結(jié)
這里介紹了bean實(shí)例化部分的getBean方法,包括先從緩存中獲取實(shí)例(getSingleton)豌熄、 FactoryBean 的 bean 創(chuàng)建(getObjectForBeanInstance)授嘀、實(shí)例化自己的依賴即dependOn變量(遞歸調(diào)用getBean來創(chuàng)建實(shí)例)、創(chuàng)建 bean 實(shí)例(createBean)锣险,以及創(chuàng)建前后一些標(biāo)記等蹄皱,createBean方法也是個(gè)很重要的方法,下一文中詳細(xì)介紹它芯肤。