概述
前面我們從registerBeanPostProcessors方法解析的時(shí)候,已經(jīng)提到了finishBeanFactoryInitialization方法脂崔。我們先越過中間的消息資源初始化以及事件監(jiān)聽的部分餐曹,來解析一下finishBeanFactoryInitialization這個(gè)方法憋他,因?yàn)槲覀儚那懊嬉呀?jīng)知道Spring IoC最重要部分就在于:obtainFreshBeanFactory国章、invokeBeanFactoryPostProcessors褐隆、registerBeanPostProcessors 和finishBeanFactoryInitialization 這四個(gè)方法,而finishBeanFactoryInitialization 又是Spring IoC的核心侦锯。
在finishBeanFactoryInitialization 方法里驼鞭,會(huì)實(shí)例化所有剩余的非懶加載單例 bean(包括一些內(nèi)部的 bean、實(shí)現(xiàn)了 BeanFactoryPostProcessor 接口的 bean率触、實(shí)現(xiàn)了 BeanPostProcessor 接口的 bean终议,以及其他的非懶加載單例 bean) , 之前注冊(cè)了的BeanPostProcessor 實(shí)現(xiàn)類也是在這里被調(diào)用執(zhí)行其方法的葱蝗。
finishBeanFactoryInitialization
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 為上下文初始化轉(zhuǎn)換服務(wù)
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// 如果beanFactory之前沒有注冊(cè)嵌入值解析器,則注冊(cè)默認(rèn)的嵌入值解析器:主要用于注解屬性值的解析细燎。
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 獲取LoadTimeWeaverAware類型的bean名稱
// 遍歷初始化LoadTimeWeaverAware Bean實(shí)例對(duì)象
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 凍結(jié)配置两曼,允許緩存所有bean定義元數(shù)據(jù),所有bean定義不會(huì)被修改或進(jìn)一步后處理
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
//注釋1. 實(shí)例化所有剩余(非懶加載)單例對(duì)象
beanFactory.preInstantiateSingletons();
}
執(zhí)行步驟按方法中的注釋往下走玻驻,比較清晰悼凑,最后到達(dá)最后一步實(shí)例化偿枕。具體來看最后一步的實(shí)例化步驟。
注釋1. 實(shí)例化所有剩余(非懶加載)單例對(duì)象 (見源碼解析1)
【源碼解析1】 beanFactory.preInstantiateSingletons
我們知道beanFactory是DefaultListableBeanFactory類型户辫,所以preInstantiateSingletons方法源碼如下:
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
//創(chuàng)建beanDefinitionNames的副本beanNames用于后續(xù)的遍歷渐夸,以允許init等方法注冊(cè)新的bean定義
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
//注釋1. 獲取beanName對(duì)應(yīng)的MergedBeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 判斷bd這個(gè)Bean實(shí)例:不是抽象類 && 是單例 && 不是懶加載
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//注釋2. 判斷beanName對(duì)應(yīng)的bean是否為FactoryBean
if (isFactoryBean(beanName)) {
//注釋2-1. getBean('&'+beanName)將得到bean本身
//通過getBean(beanName)拿到的是FactoryBean創(chuàng)建的Bean實(shí)例
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
//判斷它是不是FactoryBean類型,然后獲取FactoryBean實(shí)例
final FactoryBean<?> factory = (FactoryBean<?>) bean;
// 急切初始化標(biāo)識(shí)
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());
}
//注釋2-2. 如果需急切初始化渔欢,則通過getBean(beanName)獲取bean實(shí)例
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
//注釋2-3 如果beanName對(duì)應(yīng)的bean不是FactoryBean墓塌,只是普通Bean,通過getBean(beanName)獲取bean實(shí)例
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
// 注釋3. 遍歷beanNames奥额,觸發(fā)post-initialization 回調(diào)
for (String beanName : beanNames) {
// 獲取beanName對(duì)應(yīng)的單例bean實(shí)例
Object singletonInstance = getSingleton(beanName);
//判斷singletonInstance是否實(shí)現(xiàn)了SmartInitializingSingleton接口
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
//觸發(fā)SmartInitializingSingleton實(shí)現(xiàn)類的afterSingletonsInstantiated方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
整個(gè)流程按注釋順序下來,比較清晰苫幢。這里出現(xiàn)了兩個(gè)比較重要的名稱:MergedBeanDefinition 和FactoryBean后面一一解釋。
其中需要解析的部分如下:
注釋1. 獲取beanName對(duì)應(yīng)的MergedBeanDefinition (見源碼解析2)
注釋2. 判斷beanName對(duì)應(yīng)的bean是否為FactoryBean垫挨,isFactoryBean方法放最后解釋韩肝。 (見源碼解析4)
注釋2-2 、注釋2-3 都為getBean(beanName)獲取bean實(shí)例九榔,前者為FactoryBean實(shí)例哀峻,后者為普通bean實(shí)例。getBean是一個(gè)非常重要的方法,將在后邊詳細(xì)解析哲泊。
注釋3. 遍歷 beanNames剩蟀,觸發(fā)所有 SmartInitializingSingleton 的后初始化回調(diào),這是 Spring 提供的一個(gè)擴(kuò)展點(diǎn)攻旦,在所有非懶加載單例實(shí)例化結(jié)束后調(diào)用
【源碼解析2】 AbstractBeanFactory類中的getMergedLocalBeanDefinition方法:
// 方法1
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
//先檢查beanName對(duì)應(yīng)的MergedBeanDefinition是否存在于緩存中
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null) {
// 存在喻旷,則返回緩存
return mbd;
}
//不存在,則通過getBeanDefinition獲取BeanDefinition,然后通過beanName牢屋、BeanDefinition 獲取MergedBeanDefinition
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
// 方法2 它只是個(gè)適配器且预,交給方法3執(zhí)行
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
// 方法3,核心方法
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
// 加同步鎖
synchronized (this.mergedBeanDefinitions) {
// 定義一個(gè)mbd返回值,用于存儲(chǔ)bd的MergedBeanDefinition
RootBeanDefinition mbd = null;
// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
// 檢查beanName對(duì)應(yīng)的MergedBeanDefinition是否存在于緩存中
mbd = this.mergedBeanDefinitions.get(beanName);
}
// 如果beanName對(duì)應(yīng)的MergedBeanDefinition不存在于緩存中
if (mbd == null) {
//如果bd的parentName為空
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
//如果bd的類型為RootBeanDefinition烙无,則bd的MergedBeanDefinition就是bd本身锋谐,則直接克隆一個(gè)副本
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
//否則,將bd作為參數(shù)截酷,創(chuàng)建一個(gè)RootBeanDefinition對(duì)象
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
//注釋1. 若bd的parentName不為空涮拗,bd存在父定義,需要與父定義合并
BeanDefinition pbd;
try {
//注釋1-1. 獲取父定義的beanName
String parentBeanName = transformedBeanName(bd.getParentName());
//注釋1-2. 如果父定義的beanName與該bean的beanName不同
if (!beanName.equals(parentBeanName)) {
//注釋1-2-1. 獲取父定義的MergedBeanDefinition(因?yàn)楦付x也可能有父定義迂苛,即向上獲取合并定義...)
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
//注釋1-2-2. 如果父定義的beanName與bd的beanName相同三热,則拿到父BeanFactory
//只有在存在父BeanFactory的情況下,才允許父定義beanName與自己相同三幻,否則就是將自己設(shè)置為父定義
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
//注釋1-2-3. 如果父BeanFactory是ConfigurableBeanFactory就漾,則通過父BeanFactory獲取父定義的MergedBeanDefinition
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
//注釋1-2-4. 如果父BeanFactory不是ConfigurableBeanFactory,則拋異常
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
//注釋1-3. 深拷貝 覆蓋值
//使用父定義pbd構(gòu)建一個(gè)新的RootBeanDefinition對(duì)象
mbd = new RootBeanDefinition(pbd);
//使用bd覆蓋父定義
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
//注釋2. 如果沒有配置scope念搬,則設(shè)置成默認(rèn)的singleton
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
//注釋3. 如果containingBd不為空抑堡,
//并且 containingBd不為singleton ,
//并且 mbd為singleton摆出,則將mdb的scope設(shè)置為containingBd的scope
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
if (containingBd == null && isCacheBeanMetadata()) {
//注釋4. 將beanName與mbd放到mergedBeanDefinitions緩存,以便之后可以直接使用
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
//注釋5. 返回MergedBeanDefinition
return mbd;
}
}
//方法4. 用戶獲取父類等上層的MergedBeanDefinition
public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
// 獲取真正的beanName(解析別名)
String beanName = transformedBeanName(name);
// Efficiently check whether bean definition exists in this factory.
// 如果當(dāng)前BeanFactory中不存在beanName的Bean定義 && 父beanFactory是ConfigurableBeanFactory
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
// 則調(diào)用父BeanFactory去獲取beanName的MergedBeanDefinition
return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
}
// Resolve merged bean definition locally.
// 在當(dāng)前BeanFactory中解析beanName的MergedBeanDefinition
return getMergedLocalBeanDefinition(beanName);
}
這里出現(xiàn)了一個(gè)新名稱父 BeanFactory首妖,后面一一解釋偎漫。
注釋1-1. 獲取父定義的beanName,使用了transformedBeanName方法來獲取 (見源碼解析3)
注釋1-2-1. 獲取父定義的MergedBeanDefinition(見源碼解析1中的方法4)
注釋1-3. 深拷貝 覆蓋值,合并操作有缆,產(chǎn)生MergedBeanDefinition
注釋4. 將beanName與mbd放到mergedBeanDefinitions緩存象踊,所以方法1執(zhí)行的時(shí)候,有緩存就會(huì)獲取緩存妒貌。
【源碼解析3】 transformedBeanName
// AbstractBeanFactory類中的transformedBeanName方法
protected String transformedBeanName(String name) {
//注釋1將 name 真正解析成真正的 beanName通危,主要是去掉 FactoryBean 里的 “&” 前綴,和解析別名
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
// BeanFactoryUtils類中的transformedBeanName方法
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
// SimpleAliasRegistry類中的canonicalName方法
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
SimpleAliasRegistry為AbstractBeanFactory父類,canonicalName調(diào)用的是SimpleAliasRegistry中的方法灌曙。FACTORY_BEAN_PREFIX為'&'符,將 name 真正解析成真正的 beanName菊碟,主要是去掉 FactoryBean 里的 “&” 前綴,和解析別名在刺。
好了逆害,我們先來把前面遇到的新名稱解釋一下:
MergedBeanDefinition
MergedBeanDefinition 通過字面意思,可以看出來是 合并的Bean定義蚣驼,在執(zhí)行過程中魄幕,我們遇到了一個(gè)bean定義,它可能有父定義等情況颖杏,有以下幾種情況:
- 該 BeanDefinition 存在 “父定義”:首先使用 “父定義” 的參數(shù)構(gòu)建一個(gè) RootBeanDefinition纯陨,然后再使用該 BeanDefinition 的參數(shù)來進(jìn)行覆蓋。
- 該 BeanDefinition 不存在 “父定義”留储,并且該 BeanDefinition 的類型是 RootBeanDefinition:直接返回該 RootBeanDefinition 的一個(gè)克隆翼抠。
- 該 BeanDefinition 不存在 “父定義”,但是該 BeanDefinition 的類型不是 RootBeanDefinition:使用該 BeanDefinition 的參數(shù)構(gòu)建一個(gè) RootBeanDefinition
BeanDefinition 在之前加載到 BeanFactory 中的時(shí)候获讳,通常是被封裝成 GenericBeanDefinition 或 ScannedGenericBeanDefinition阴颖,但是從這邊之后 bean 的后續(xù)流程處理都是針對(duì) RootBeanDefinition,因此在這邊會(huì)統(tǒng)一將 BeanDefinition 轉(zhuǎn)換成 RootBeanDefinition丐膝。
如果我們使用 XML 配置來注冊(cè) bean量愧,則該 bean 定義會(huì)被封裝成:GenericBeanDefinition;如果我們使用注解的方式來注冊(cè) bean帅矗,也就是<context:component-scan /> 或 @Compoment偎肃,則該 bean 定義會(huì)被封裝成 ScannedGenericBeanDefinition
FactoryBean
通常初學(xué)者比較容易被BeanFactory和FactoryBean攪渾,其實(shí)很容易區(qū)分浑此,前面我們已經(jīng)介紹過BeanFactory接口软棺,是IOC容器或?qū)ο蠊S,它是Spring IOC的基礎(chǔ)尤勋,在Spring中喘落,所有的Bean都是由BeanFactory(也就是IOC容器)來進(jìn)行管理。
一般情況下最冰,Spring通過反射機(jī)制利用bean的class屬性指定實(shí)現(xiàn)類實(shí)例化Bean瘦棋,在某些情況下,實(shí)例化Bean過程比較復(fù)雜暖哨,如果按照傳統(tǒng)的方式赌朋,則需要在<bean>中提供大量的配置信息。配置方式的靈活性是受限的篇裁,這時(shí)采用編碼的方式可能會(huì)得到一個(gè)簡(jiǎn)單的方案沛慢。
FactoryBean,是一種特殊的bean, 它是個(gè)工廠 bean达布,可以自己創(chuàng)建 bean 實(shí)例团甲,如果一個(gè)類實(shí)現(xiàn)了 FactoryBean 接口全陨,則該類可以自己定義創(chuàng)建實(shí)例對(duì)象的方法仑嗅,只需要實(shí)現(xiàn)它的 getObject() 方法。
為了區(qū)分 “FactoryBean” 和 “FactoryBean 創(chuàng)建的 bean 實(shí)例”雄坪,Spring 使用了 “&” 前綴产还。Spring里有很多類實(shí)現(xiàn)了FactoryBean匹厘,那我們找一個(gè) beanName 為 gson的,則 getBean("gson") 獲得的是 MapperFactoryBean 通過 getObject() 方法創(chuàng)建的Gson bean 實(shí)例脐区;而 getBean("&gson") 獲得的是 GsonFactoryBean本身愈诚。
父BeanFactory
在 Spring 中可能存在多個(gè) BeanFactory,多個(gè) BeanFactory 可能存在 “父工廠” 與 “子工廠” 的關(guān)系牛隅。最常見的例子就是:Spring MVC 的 BeanFactory 和 Spring 的 BeanFactory炕柔,通常情況下,Spring 的 BeanFactory 是 “父工廠”倔叼,Spring MVC 的 BeanFactory 是 “子工廠”汗唱,在 Spring 中,子工廠可以使用父工廠的 BeanDefinition丈攒,因而哩罪,如果在當(dāng)前 BeanFactory 中找不到,而又存在父工廠巡验,則會(huì)去父工廠中查找际插。
【源碼解析4】 執(zhí)行的該isFactoryBean方法,在AbstractBeanFactory類中
// 方法1
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
// 轉(zhuǎn)換beanName,獲取真正的beanName(去掉&前綴显设、解析別名)
String beanName = transformedBeanName(name);
//注釋1. 獲取beanName對(duì)應(yīng)的單例bean實(shí)例
Object beanInstance = getSingleton(beanName, false);
if (beanInstance != null) {
//beanInstance存在框弛,則直接判斷其類型是否為FactoryBean
return (beanInstance instanceof FactoryBean);
}
// No singleton instance found -> check bean definition.
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
// 如果緩存中不存在此beanName
// 并且父beanFactory是ConfigurableBeanFactory,
// 則調(diào)用父BeanFactory判斷是否為FactoryBean
return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
}
//注釋2. 通過MergedBeanDefinition來檢查beanName對(duì)應(yīng)的Bean是否為FactoryBean
return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}
// 方法2
protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
// 拿到beanName對(duì)應(yīng)的Bean實(shí)例的類型
Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
return (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
}
注釋1. 獲取beanName對(duì)應(yīng)的單例bean實(shí)例(見源碼解析5)
注釋2. 通過 MergedBeanDefinition 來檢查 beanName 對(duì)應(yīng)的 bean 是否為 FactoryBean捕捂。首先通過 getMergedLocalBeanDefinition 方法獲取 beanName 的 MergedBeanDefinition瑟枫,接著調(diào)用 isFactoryBean 來檢查 beanName 對(duì)應(yīng)的 bean 是否為 FactoryBean斗搞。
這里的isFactoryBean 方法為上面方法2,其調(diào)用了predictBeanType方法來獲取beanName對(duì)應(yīng)的Bean實(shí)例的類型(見源碼解析6)慷妙,然后通過isAssignableFrom方法來判斷beanType是否與FactoryBean接口類型相同僻焚。
【源碼解析5】 getSingleton方法,在DefaultSingletonBeanRegistry類中膝擂,
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//從單例對(duì)象緩存中獲取beanName對(duì)應(yīng)的單例對(duì)象
Object singletonObject = this.singletonObjects.get(beanName);
// 檢查緩存中是否存在實(shí)例
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 加鎖進(jìn)行操作虑啤,公共變量都需要加鎖操作,避免多線程并發(fā)修改
synchronized (this.singletonObjects) {
// 從早期單例對(duì)象緩存中獲取單例對(duì)象(之所稱成為早期單例對(duì)象架馋,是因?yàn)? //earlySingletonObjects里的對(duì)象的都是通過提前曝光的ObjectFactory創(chuàng)建出來的狞山,還未進(jìn)行屬性填充等操作)
singletonObject = this.earlySingletonObjects.get(beanName);
//如果在早期單例對(duì)象緩存中也沒有,并且允許創(chuàng)建早期單例對(duì)象引用
if (singletonObject == null && allowEarlyReference) {
// 從單例工廠緩存中獲取beanName的單例工廠
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//如果存在單例對(duì)象工廠叉寂,則通過工廠創(chuàng)建一個(gè)單例對(duì)象
singletonObject = singletonFactory.getObject();
//將通過單例對(duì)象工廠創(chuàng)建的單例對(duì)象萍启,放到早期單例對(duì)象緩存中
this.earlySingletonObjects.put(beanName, singletonObject);
//移除該beanName對(duì)應(yīng)的單例對(duì)象工廠,因?yàn)樵搯卫S已經(jīng)創(chuàng)建了一個(gè)實(shí)例對(duì)象办绝,并且放到earlySingletonObjects緩存了
this.singletonFactories.remove(beanName);
}
}
}
}
//返回單例對(duì)象
return singletonObject;
}
主要操作步驟就是檢查下我們要拿的 bean 實(shí)例是否存在于緩存中伊约,如果有就返回緩存中的 bean 實(shí)例,否則就返回 null孕蝉。
Spring 解決循環(huán)依賴的核心就是依賴這里的代碼屡律,所以它是一段比較重要的代碼。
解決循環(huán)依賴邏輯:使用構(gòu)造函數(shù)創(chuàng)建一個(gè) “不完整” 的 bean 實(shí)例(之所以說不完整降淮,是因?yàn)榇藭r(shí)該 bean 實(shí)例還未初始化)超埋,并且提前曝光該 bean 實(shí)例的 ObjectFactory(提前曝光就是將 ObjectFactory 放到 singletonFactories 緩存),通過 ObjectFactory 我們可以拿到該 bean 實(shí)例的引用佳鳖,如果出現(xiàn)循環(huán)引用霍殴,我們可以通過緩存中的 ObjectFactory 來拿到 bean 實(shí)例,從而避免出現(xiàn)循環(huán)引用導(dǎo)致的死循環(huán)系吩。這邊通過緩存中的 ObjectFactory 拿到的 bean 實(shí)例雖然拿到的是 “不完整” 的 bean 實(shí)例来庭,但是由于是單例,所以后續(xù)初始化完成后穿挨,該 bean 實(shí)例的引用地址并不會(huì)變月弛,所以最終我們看到的還是完整 bean 實(shí)例。
這段解決邏輯涉及到了后面的一些內(nèi)容科盛,所以可能會(huì)看的不是很理解帽衙,可以先有個(gè)印象,等把創(chuàng)建 bean 實(shí)例都看完了贞绵,再回過頭來看厉萝,可能會(huì)好理解一點(diǎn)。
另外這個(gè)代碼塊中引進(jìn)了4個(gè)重要緩存:
- singletonObjects 緩存:beanName -> 單例 bean 對(duì)象。
- earlySingletonObjects 緩存:beanName -> 單例 bean 對(duì)象谴垫,該緩存存放的是早期單例 bean 對(duì)象章母,可以理解成還未進(jìn)行屬性填充、初始化弹渔。
- singletonFactories 緩存:beanName -> ObjectFactory胳施。
- singletonsCurrentlyInCreation 緩存:當(dāng)前正在創(chuàng)建單例 bean 對(duì)象的 beanName 集合。
singletonObjects肢专、earlySingletonObjects、singletonFactories 在這邊構(gòu)成了一個(gè)類似于 “三級(jí)緩存” 的概念焦辅。
【源碼解析6】 predictBeanType方法,在AbstractAutowireCapableBeanFactory類中
@Override
@Nullable
protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
//獲取beanName的類型
Class<?> targetType = determineTargetType(beanName, mbd, typesToMatch);
// Apply SmartInstantiationAwareBeanPostProcessors to predict the
// eventual type after a before-instantiation shortcut.
// 2.應(yīng)用SmartInstantiationAwareBeanPostProcessors后置處理器博杖,來預(yù)測(cè)實(shí)例化的最終類型,
// SmartInstantiationAwareBeanPostProcessors繼承了InstantiationAwareBeanPostProcessor筷登,
// InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法可以改變Bean實(shí)例的類型剃根,
// 而SmartInstantiationAwareBeanPostProcessors的predictBeanType方法可以預(yù)測(cè)這個(gè)類型
if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
//調(diào)用predictBeanType方法
Class<?> predicted = ibp.predictBeanType(targetType, beanName);
if (predicted != null && (typesToMatch.length != 1 || FactoryBean.class != typesToMatch[0] ||
FactoryBean.class.isAssignableFrom(predicted))) {
//如果predicted不為空,并且
//(typesToMatch長(zhǎng)度不為1或typesToMatch[0]不為FactoryBean.class或predicted是FactoryBean本身前方、子類或子接口)
//返回predicted
return predicted;
}
}
}
}
//返回beanName的類型
return targetType;
}
這邊執(zhí)行的是 AbstractAutowireCapableBeanFactory 里的方法狈醉,而不是 AbstractBeanFactory 里的方法。
通過前面的介紹惠险,我們知道創(chuàng)建的 BeanFactory 為 DefaultListableBeanFactory苗傅,而 DefaultListableBeanFactory 繼承了 AbstractAutowireCapableBeanFactory,因此這邊會(huì)走 AbstractAutowireCapableBeanFactory 的重寫方法班巩。
總結(jié)
通過finishBeanFactoryInitialization方法的解析渣慕,知道這里是如何創(chuàng)建 bean 實(shí)例的,以及bean實(shí)例化之前的一些準(zhǔn)備操作抱慌。主要是引入了 FactoryBean 這一特殊的 bean逊桦,獲取 BeanDefinition 的 MergedBeanDefinition,最后將 BeanDefinition 統(tǒng)一轉(zhuǎn)換成 RootBeanDefinition抑进。
中間還學(xué)習(xí)了Spring如何解決循環(huán)依賴的問題强经,是通過緩存。
Spring 中大量使用了本地緩存寺渗,基本上通過名字和注釋就能理解緩存的作用了匿情。
這里用到的幾個(gè)緩存:
- mergedBeanDefinitions 緩存:beanName -> 合并的 bean 定義。
- beanDefinitionMap 緩存:beanName -> BeanDefinition户秤。
- singletonObjects 緩存:beanName -> 單例 bean 對(duì)象码秉。
- earlySingletonObjects 緩存:beanName -> 單例 bean 對(duì)象,該緩存存放的是早期單例 bean 對(duì)象鸡号,可以理解成還未進(jìn)行屬性填充转砖、初始化。
- singletonFactories 緩存:beanName -> ObjectFactory。
- singletonsCurrentlyInCreation 緩存:當(dāng)前正在創(chuàng)建單例 bean 對(duì)象的 beanName 集合府蔗。