本文會介紹上文中提到的<1>,<2>,<3>這三個步驟的內容
1 transformedBeanName
final String beanName = transformedBeanName(name);
這段代碼的作用主要有兩個:
1.如果傳入的bean name是別名,那么就要獲取對應的真實的bean name。也會存在循環別名即別名B指向別名A,別名A指向真實的bean name的情況。
2.去掉"&"符號,獲取真實的bean name。如:name從"&MyBean"變成"MyBean"。
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
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;
});
}
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
// 遞歸獲取別名對應的beanName
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
2 getSingleton
spring為了避免創建單例時出現循環依賴的問題,所以創建bean的時候不等bean創建完成就會創建bean的ObjectFactory提早曝光加入到緩存中,一旦下一個bean創建時需要依賴這個bean就直接使用ObjectFactory。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 從單例緩存中加載 bean
Object singletonObject = this.singletonObjects.get(beanName);
// 緩存中的 bean 為空,且當前 bean 正在創建(注:第七步創建單例類型bean的時候會保存在一個緩存中)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 從 earlySingletonObjects 獲取,表示此bean正在創建,不進行后續處理
singletonObject = this.earlySingletonObjects.get(beanName);
// earlySingletonObjects 中沒有,且允許提前創建
if (singletonObject == null && allowEarlyReference) {
// 從 singletonFactories 中獲取對應的 ObjectFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 獲得 bean
// 對應第7步中的 getEarlyBeanReference(beanName, mbd, bean)
singletonObject = singletonFactory.getObject();
// 添加 bean 到 earlySingletonObjects 中
this.earlySingletonObjects.put(beanName, singletonObject);
// 從 singletonFactories 中移除對應的 ObjectFactory
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
最大的難點可能在于其中的好幾個map對象到底是什么意思,下面來簡單介紹下:
1.singletonObjects(一級緩存):保存beanName與bean實例之間的關系。
那么這個里面的數據來自哪里呢?答案在 bean 加載過程中的第7步
DefaultSingletonBeanRegistry#getSingleton(創建單例模式的java bean)
-> DefaultSingletonBeanRegistry#addSingleton方法
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
從二級和三級緩存中刪除,添加到一級緩存中
2.earlySingletonObjects(二級緩存):也是保存beanName與bean實例之間的關系,與singletonObjects不同的地方是,當bean還在創建過程中的時候就可以通過這個map拿到對應的bean實例,相當于保存的是半成品的bean,用來檢測循環引用。
3.singletonFactories(三級緩存):保存beanName與創建bean的工廠之間的關系。這個map中的數據來源于,bean 加載過程中的第7步
AbstractAutowireCapableBeanFactory#createBean
-> AbstractAutowireCapableBeanFactory#doCreateBean
-> DefaultSingletonBeanRegistry#addSingletonFactory
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);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
從三級緩存中刪除,加入二級緩存。由此可以看到二級緩存和三級緩存其實是互斥的
總的三級緩存的使用邏輯大概是:
在A的創建過程中會添加三級緩存,然后進行A的屬性填充,如果此時A依賴了B,那么需要首先創建B。當B的創建又需要用到A,就會從三級緩存中獲取,然后通過singletonFactory.getObject()獲取初始A對象(沒有初始化和填充屬性,但是經過了AOP代理),放入二級緩存并且刪除三級緩存,返回半成品的A作為B的屬性,然后B的創建就完成了。返回A的創建中,當A創建完成后,刪除二級和三級緩存,之后的A獲取都可以在一級緩存中拿到。
從這里可以看出來,就算是使用一級和二級緩存也能實現解決循環依賴的問題,那為什么還要使用三級緩存呢?原因主要是:二級緩存放入的是實例化后的半成品對象,如果這個對象還需要實現AOP功能,那么就需要使用ObjectFactory包裝然后放入三級緩存中。然后在第三步的getObjectForBeanInstance方法中,取出ObjectFactory包裝的AOP之后的對象。
3 getObjectForBeanInstance
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 若為工廠類引用(name 以 & 開頭)
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 類型不為 FactoryBean
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
}
// 到這里就有了一個 Bean 實例,當然該實例可能是會是一個正常的 bean 又或者是一個 FactoryBean
// 如果是 FactoryBean 并且 name 中有 & 符號,則直接返回,否則使用 FactoryBean 創建bean
// 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.
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
// 若 BeanDefinition 為 null,則從緩存中加載 Bean 對象
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
// 若 object 依然為空,則可以確認,beanInstance 一定是 FactoryBean 。從而,使用 FactoryBean 獲得 Bean 對象
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
// containsBeanDefinition 檢測 beanDefinitionMap 中也就是在所有已經加載的類中
// 檢測所有已經加載的bean是否包含 beanName
if (mbd == null && containsBeanDefinition(beanName)) {
// 將存儲 XML 配置文件的 GenericBeanDefinition 轉換為 RootBeanDefinition,
// 如果指定 BeanName 是子 Bean 的話同時會合并父類的相關屬性
mbd = getMergedLocalBeanDefinition(beanName);
}
// 是否是用戶定義的,而不是應用程序本身定義的
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 核心處理方法,使用 FactoryBean 獲得 Bean 對象
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
其中最核心的是getObjectFromFactoryBean,接下來看看這個方法。
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 為單例模式且緩存中存在
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
// 從緩存中獲取指定的 factoryBean
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 為空,則從 FactoryBean 中獲取對象
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) {
object = alreadyThere;
}
else {
// 需要后續處理
if (shouldPostProcess) {
// 若該 Bean 處于創建中,則返回非處理對象,而不是存儲它
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
// 單例 Bean 的前置處理
// 設置該bean正在創建過程中
beforeSingletonCreation(beanName);
try {
// 對從 FactoryBean 獲取的對象進行后處理
// 生成的對象將暴露給 bean 引用
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
// 單例 Bean 的后置處理
// 移除該bean正在創建
afterSingletonCreation(beanName);
}
}
// 添加到 factoryBeanObjectCache 中,進行緩存
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
// 為空,則從 FactoryBean 中獲取對象
Object object = doGetObjectFromFactoryBean(factory, beanName);
// 需要后續處理
if (shouldPostProcess) {
try {
// 對從 FactoryBean 獲取的對象進行后處理
// 生成的對象將暴露給 bean 引用
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
這里把這個代碼拆分成if和else看。
3.1 if塊代碼
當bean是單例的并且已經存在緩存中。獲取同步鎖,如果能夠獲取到對應的FactoryBean就直接返回,否則通過傳入的factory#getObject獲取對象并且進行后置處理。
3.1.1 doGetObjectFromFactoryBean
權限驗證以及通過 factory#getObject 方法獲取對象。
3.1.2 后置處理
3.1.2.1 beforeSingletonCreation
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
校驗當前bean沒有在檢測并且設置正在創建
3.1.2.2 postProcessObjectFromFactoryBean
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 獲取 BeanPostProcessor 數組
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 循環調用 postProcessAfterInitialization 方法,如果為空立即返回
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
BeanPostProcessor 也就是后置處理器,可用于類增強。后續專門介紹
3.1.2.3 afterSingletonCreation
校驗當前bean沒有在檢測并且移除正在創建
3.2 else
bean不是單例對象,直接通過 factory#getObject 方法獲取對象,并且進行后置處理。