如果緩存中沒有單例Bean的緩存,則需要從頭開始創(chuàng)建單例Bean,這主要是重載getSingleton的重載方法來實(shí)現(xiàn)單例Bean的加載。
getSingleton方法
3. 獲取單例
/**
* Return the (raw) singleton object registered under the given name,
* creating and registering a new one if none registered yet.
* @param beanName the name of the bean
* @param singletonFactory the ObjectFactory to lazily create the singleton
* with, if necessary
* @return the registered singleton object
*/
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 (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
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 != NULL_OBJECT ? singletonObject : null);
}
}
前后處理方法:
3.1
/**
* Callback before singleton creation.
* <p>The default implementation register the singleton as currently in creation.
* @param beanName the name of the singleton about to be created
* @see #isSingletonCurrentlyInCreation
*/
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
3.2
/**
* Callback after singleton creation.
* <p>The default implementation marks the singleton as not in creation anymore.
* @param beanName the name of the singleton that has been created
* @see #isSingletonCurrentlyInCreation
*/
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
3.3
/**
* Add the given singleton object to the singleton cache of this factory.
* <p>To be called for eager registration of singletons.
* @param beanName the name of the bean
* @param singletonObject the singleton object
*/
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
3.4 從3返回
sharedInstances = getSingleton(String beanName, ObjectFactory<?> singletonFactory)
這個(gè)方法只是做一些準(zhǔn)備以及處理操作,而真正的獲取單例bean的方法其實(shí)并不是在此方法中實(shí)現(xiàn)的,其實(shí)現(xiàn)邏輯是在ObjectFactory類型的實(shí)例singletonFactory中實(shí)現(xiàn)的。
準(zhǔn)備及處理操作如下:
首先獲取SingletonObjects的對(duì)象鎖,保證單例的全局唯一性。
檢查緩存是否已經(jīng)加載過。
若沒有加載,則記錄beanName的正在加載狀態(tài)
-
加載單例前記錄加載狀態(tài)
beforeSingletonCreation()方法用于記錄加載的狀態(tài):
調(diào)用this.singletonsCurrentlyInCreation.add(beanName)將當(dāng)前正要?jiǎng)?chuàng)建的bean記錄在緩存中,這樣便可以對(duì)循環(huán)依賴進(jìn)行檢測啦 -
通過調(diào)用參數(shù)傳入的ObjectFactory的getObject方法實(shí)例化bean
singletonObject = singletonFactory.getObject(); -
加載單例后的處理方法調(diào)用
當(dāng)bean加載結(jié)束后需要移除緩存中對(duì)該bean的正在加載狀態(tài)的記錄: afterSingletonCreation()方法調(diào)用
-
將結(jié)果記錄至緩存并刪除加載bean過程中所有記錄的各種輔助狀態(tài)
調(diào)用addSingleton()方法
-
返回處理結(jié)果
上述是加載bean的邏輯框架,現(xiàn)在為止還沒有對(duì)bean加載功能的探索,其實(shí)bean的加載邏輯是在傳入的ObjectFactory類型的參數(shù)singletonFactory中定義的,而ObjectFactory的核心代碼只是調(diào)用了createBean的方法,接下來就去探究一下這個(gè)方法的奧妙。
createBean方法詳解
準(zhǔn)備創(chuàng)建bean(createBean方法詳解)
beans.factory.support.AbstractAutowireCapableBeanFactory
//---------------------------------------------------------------------
// Implementation of relevant AbstractBeanFactory template methods
//---------------------------------------------------------------------
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
createBean方法主要步驟:
根據(jù)設(shè)置的class屬性或者根據(jù)className來解析Class。
對(duì)override屬性進(jìn)行標(biāo)記以及驗(yàn)證(是針對(duì)Spring配置中l(wèi)ookup-method、replace-method bean的子標(biāo)簽進(jìn)行處理,因?yàn)檫@兩個(gè)子標(biāo)簽的加載過程就是將配置統(tǒng)一存放在BeanDefinition中的methodOverride屬性里)。
應(yīng)用實(shí)例前的后處理器,給后處理器一個(gè)返回代理而不是目標(biāo)bean實(shí)例的機(jī)會(huì),如果返回的代理類不為空則直接返回,而不會(huì)進(jìn)行下面的創(chuàng)建bean的過程。
創(chuàng)建bean(doCreateBean方法)。這又是一個(gè)比較重要而且復(fù)雜的過程,需要仔細(xì)分析。
下面重點(diǎn)講解步驟2、3、4。
步驟2- 處理override屬性
用于處理配置中的lookup-method以及replace-method屬性。
主要完成的工作:
- 標(biāo)記
如果一個(gè)類中存在若干個(gè)重載方法,方法調(diào)用以及增強(qiáng)的時(shí)候還需要根據(jù)參數(shù)類型進(jìn)行匹配,來最終確定當(dāng)前調(diào)用的是哪個(gè)方法,Spring在這里將匹配的工作在這里完成匹配的,這樣在后續(xù)調(diào)用的時(shí)候變可以直接是我用找到的方法,而不需要進(jìn)行方法的參數(shù)匹配驗(yàn)證了
- 驗(yàn)證
在標(biāo)記的過程中可以對(duì)方法存在性進(jìn)行驗(yàn)證,一箭雙雕。
4.1 處理override屬性
beans.factory.support.AbstractBeanFactory(XmlBeanFactory 繼承自這個(gè)類,擁有這個(gè)方法)
/**
* Validate and prepare the method overrides defined for this bean.
* Checks for existence of a method with the specified name.
* @throws BeanDefinitionValidationException in case of validation failure
*/
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exists.
MethodOverrides methodOverrides = getMethodOverrides();
if (!methodOverrides.isEmpty()) {
Set<MethodOverride> overrides = methodOverrides.getOverrides();
synchronized (overrides) {
for (MethodOverride mo : overrides) {
prepareMethodOverride(mo);
}
}
}
}
/**
* Validate and prepare the given method override.
* Checks for existence of a method with the specified name,
* marking it as not overloaded if none found.
* @param mo the MethodOverride object to validate
* @throws BeanDefinitionValidationException in case of validation failure
*/
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
}
else if (count == 1) {
// Mark override as not overloaded, to avoid the overhead of arg type checking.
mo.setOverloaded(false);
}
}
步驟3- 實(shí)例化前的的后處理
doCreateBean()方法之前調(diào)用了resolveBeforeInstantiation方法對(duì)BeanDefinition中的屬性進(jìn)行前置處理。
調(diào)用實(shí)例化前處理器進(jìn)行處理。
短路判斷:如果前置處理返回的結(jié)果不為空,則直接略過后續(xù)Bean的創(chuàng)建而直接返回結(jié)果,這一特性至關(guān)重要,AOP功能就是基于這里的判斷的,如果不為空則調(diào)用初始化后處理器。
實(shí)例化的前置處理
beans.factory.support.AbstractAutowireCapableBeanFactory
/**
* Apply before-instantiation post-processors, resolving whether there is a
* before-instantiation shortcut for the specified bean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the shortcut-determined bean instance, or {@code null} if none
*/
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
4.2.1 初始化前的后處理器
/**
* Apply InstantiationAwareBeanPostProcessors to the specified bean definition
* (by class and name), invoking their {@code postProcessBeforeInstantiation} methods.
* <p>Any returned object will be used as the bean instead of actually instantiating
* the target bean. A {@code null} return value from the post-processor will
* result in the target bean being instantiated.
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return the bean object to use instead of a default instance of the target bean, or {@code null}
* @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
*/
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
4.2.2 實(shí)例化后的后處理器
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
實(shí)例化前的后處理器的應(yīng)用
將AbstractBeanDefinition轉(zhuǎn)換為BeanWrapper前的處理,給子類一個(gè)修改BeanDefinition的機(jī)會(huì),也就是說當(dāng)程序經(jīng)過這個(gè)方法之后,bean可能已經(jīng)不是我們認(rèn)為的bean了,而是或許成為一個(gè)經(jīng)過處理的代理bean,可能是通過cglib生成的,也可能是通過其他技術(shù)生成的,會(huì)在AOP中進(jìn)行講解,需要清楚的是在bean的實(shí)例化前會(huì)調(diào)用后處理器的方法進(jìn)行處理。
初始化后的后處理器
Spring保證bean初始化后盡可能將注冊(cè)的后處理器postProcessAfterInitialization方法應(yīng)用到該bean中。