前言:疫情期間,在家辦公,雖說有種種不便,與此同時,也有了充足的時間,學習了一些想學習的知識,如有錯誤,敬請指出。
1:解讀
spring的主要功能是IOC與AOP,此章節暫時不講述AOP,但針對IOC來講,getBean()方法是重中之重,例如下面這個例子,我們這樣做就可以從容器中取出一個bean的實例
AnnotationConfigApplicationContext configApplicationContext=new AnnotationConfigApplicationContext(ProductServiceApplication.class);
configApplicationContext.getBean("test");
在整個spring源碼之中,new AnnotationConfigApplicationContext(ProductServiceApplication.class)可以說初始化方法佔據了極大的一部分,今天,不講述初始化的過程,單純從源碼角度講述getBean的工作流程
2:調用鏈說明
AnnotationConfigApplicationContext.getBean-->AbstractBeanFactory.getBean-->AbstractBeanFactory.doGetBean-->AbstractBeanFactory.getSingleton-->AbstractBeanFactory.createBean
上面是主要的流程,可以看出,getBean的真正獲取,是在BeanFactory裏面實現的,只不過AnnotationConfigContext裏面有bean工廠的實例,最終的bean的創建是在beanFactory裏面完成的
spring的方法命名規範也很有意思,幾個getBean的方法其實沒有做什麼事情,最終是在doGetBean和getSignleton與createBean裏面完成的。因此,代碼解析在doGetBean(AbstractBeanFactory)開始。(由於電腦原因,down下來的spring源碼已經丟了,只能看反編譯過的代碼,出入不大)
3:doGetBean解析
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
//獲取bean的名稱(因爲存在FactoryBean,以後的博客再講)
final String beanName = this.transformedBeanName(name);
//緩存,如果單例池中有的話就從單例池中獲取,沒有的話再創建,這個方法重要,解決循環依賴也是在這操作的
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
//如果緩存池中存在
if (this.logger.isDebugEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
}
if (!typeCheckOnly) {
this.markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
//又是一個重要的代碼
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
} catch (BeansException var2) {
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
與流程無關的代碼已經被我刪減了,可以看這些重要的代碼。
(1):final String beanName = this.transformedBeanName(name);這主要是獲取bean的一個名稱,這麼解釋可能有些人有疑問了,不是我們getBean的時候已經把bean的名稱傳遞進來了麼,這麼做的原因是因爲存在一種特殊的bean(FactoryBean),之後會單開一講專門講解這個(很重要,一些三方框架例如mybatis與spring整合的時候就用到這個了)
(2):Object sharedInstance = this.getSingleton(beanName);主要是從單例池中獲取bean,因爲我們getBean獲取的事單例模式的,所以假設我們之前創建過的時候不會重複創建,直接在單例池中取出來返回,而且這也是spring解決循環依賴的重要部分(不懂什麼叫循環依賴的同學自行百度)
看下這塊的代碼邏輯
public Object getSingleton(String beanName) {
return this.getSingleton(beanName, true);
}
//參數allowEarlyReference的意思是是否允許提前創建,spring解決循環依賴就是通過允許提前創建一個實例來解決的
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//singletonObjects單例池對象,存儲單例對象的一個map
Object singletonObject = this.singletonObjects.get(beanName);
//如果單例池中不存在&並且這個對象正在創建
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
synchronized(this.singletonObjects) {
//earlySingletonObjects(提前創建的bean的單例池)
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//還是空,beanFactory.getBean方法獲取
singletonObject = singletonFactory.getObject();
//放入提前創建的單例池中
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject != NULL_OBJECT ? singletonObject : null;
}
getSignleton()方法的主要功能是看單例池中是否存在這個對象,存在返回,不存在則繼續進行(關於earlySingletonObjects與singletonFactory可以暫時不用關注,結合後面內容一起理解)
(3):getSignleton(String beanName,ObjectFactory objectFacorty)注意區別下上面的getSingle方法,這裏進入了BeanFactory真正創建單例對象的過程
sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
//這裏是獲取一個FactoryBean對象
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
} catch (BeansException var2) {
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
這其中應用到了好多後置處理器的地方,暫時不進行講解,後面會抽時間吶出專門的篇章進行介紹後置處理器(Spring AOP功能就是利用後置處理器完成的)
進入getSignleton(beanName,FactoryBean factoryBean)方法內部
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' 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 (this.logger.isDebugEnabled()) {
this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//將這個beanName加入singletonsCurrentlyInCreation集合裏面(代表正在創建此對象)
this.beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = this.suppressedExceptions == null;
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
//調用剛剛說的自己創建的FactoryBean進行創建對象
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException var16) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
BeanCreationException ex = var17;
if (recordSuppressedExceptions) {
Iterator var8 = this.suppressedExceptions.iterator();
while(var8.hasNext()) {
Exception suppressedException = (Exception)var8.next();
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//不用關注,校驗
this.afterSingletonCreation(beanName);
}
if (newSingleton) {
//如果是第一次創建這個對象,需要把這個對象加入到singletonObjects單例池,並且從singletonFactories與earlySingletonObjects移除他,這兩個map的作用會在循環依賴中講到
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject != NULL_OBJECT ? singletonObject : null;
}
}
總結下getSignleton(beanName,FactoryBean factoryBean)方法
【1】:單例緩存池中沒有的話再創建
【2】:調用傳進來的FactoryBean的getBean方法獲取對象
【3】:創建末尾,將創建好的對象加入單例池,並且從singletonFactories與earlySinletonObjects中移除這個beanName。
重點關注【2】,我們在調用這個方法的時候自己創建了一個beanFactory並且,因此,創建的主要邏輯就在這裏面了
sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
//這裏是獲取一個FactoryBean對象--創建對象的主要邏輯了
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
} catch (BeansException var2) {
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
(4):AbstractBeanFactory.createBean(beanName,mbd,args)【不重要的代碼塊已刪除】
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
Object beanInstance;
try {
//這裏本來想刪除來,但是這裏是實現代理的重要地方,利用後置處理器完成,暫時保留,但是不講解,在獲取bean的時候【沒有代理的時候】沒有用,可以忽略,等將後置處理器的時候再進行講解
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if (beanInstance != null) {
return beanInstance;
}
} catch (Throwable var8) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var8);
}
//又是相似的命名邏輯,createBean-->doCreateBean,真正操作的邏輯都是在do開頭的方法裏面
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
createBean裏面又調用了doCreateBean,真正的邏輯再doCreateBean裏面,方法命名形式眼熟不,(getSingleton-->doGetSingleton)
因此,我們到doCreateBean裏面看下真正的操作(這個方法很複雜+重要,spring的後置處理器在這裏體現的淋漓盡致)
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
//BeanWrapper 可以理解爲bean的包裝類,BeanWrapper我們可以獲取到bean
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null;
Class<?> beanType = instanceWrapper != null ? instanceWrapper.getWrappedClass() : null;
mbd.resolvedTargetType = beanType;
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//bean的後置處理器--暫時可以忽略
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
}
mbd.postProcessed = true;
}
}
//判斷我們這個bean是否可以被提前創建-說白了就是可以不可以被循環依賴
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
//如果可以循環依賴的話就把bean加入到singletonfactory中,之後單獨拿出來寫一下如何解決的循環依賴
this.addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
//屬性注入,也是利用後置處理器完成的【又是一塊很複雜且重要的代碼】
this.populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
}
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
//這裏有代碼,不重要,已刪除
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
4:結語
以上,就是spring getBean的源碼概覽,挖了很多坑,例如,spring是如何解決循環依賴的;spring後置處理器如何操作,在getBean的過程中如何在哪裏有應用後置處理器;spring如何進行屬性注入【其實也是利用後置處理器】;再進一步,spring aop是怎麼實現的【也是在getBean這個實現的】。接下來的一段時間,會慢慢把這些坑給填上的~