如果緩存中沒有單例Bean的緩存,則需要從頭開始創(chuàng)建單例Bean怠缸,這主要是重載getSingleton的重載方法來實現(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)
這個方法只是做一些準備以及處理操作半醉,而真正的獲取單例bean的方法其實并不是在此方法中實現(xiàn)的,其實現(xiàn)邏輯是在ObjectFactory類型的實例singletonFactory中實現(xiàn)的缩多。
準備及處理操作如下:
首先獲取SingletonObjects的對象鎖衬吆,保證單例的全局唯一性。
檢查緩存是否已經(jīng)加載過姆泻。
若沒有加載冒嫡,則記錄beanName的正在加載狀態(tài)
-
加載單例前記錄加載狀態(tài)
beforeSingletonCreation()方法用于記錄加載的狀態(tài):
調(diào)用this.singletonsCurrentlyInCreation.add(beanName)將當前正要創(chuàng)建的bean記錄在緩存中孝凌,這樣便可以對循環(huán)依賴進行檢測啦 -
通過調(diào)用參數(shù)傳入的ObjectFactory的getObject方法實例化bean
singletonObject = singletonFactory.getObject();
-
加載單例后的處理方法調(diào)用
當bean加載結(jié)束后需要移除緩存中對該bean的正在加載狀態(tài)的記錄: afterSingletonCreation()方法調(diào)用
-
將結(jié)果記錄至緩存并刪除加載bean過程中所有記錄的各種輔助狀態(tài)
調(diào)用addSingleton()方法
-
返回處理結(jié)果
上述是加載bean的邏輯框架,現(xiàn)在為止還沒有對bean加載功能的探索峻呛,其實bean的加載邏輯是在傳入的ObjectFactory類型的參數(shù)singletonFactory中定義的辜窑,而ObjectFactory的核心代碼只是調(diào)用了createBean的方法,接下來就去探究一下這個方法的奧妙牙勘。
createBean方法詳解
準備創(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ù)設置的class屬性或者根據(jù)className來解析Class。
對override屬性進行標記以及驗證(是針對Spring配置中l(wèi)ookup-method色徘、replace-method bean的子標簽進行處理褂策,因為這兩個子標簽的加載過程就是將配置統(tǒng)一存放在BeanDefinition中的methodOverride屬性里)。
應用實例前的后處理器耿焊,給后處理器一個返回代理而不是目標bean實例的機會遍搞,如果返回的代理類不為空則直接返回,而不會進行下面的創(chuàng)建bean的過程钩杰。
創(chuàng)建bean(doCreateBean方法)诊县。這又是一個比較重要而且復雜的過程,需要仔細分析垂睬。
下面重點講解步驟2抗悍、3、4赏壹。
步驟2- 處理override屬性
用于處理配置中的lookup-method以及replace-method屬性衔沼。
主要完成的工作:
- 標記
如果一個類中存在若干個重載方法,方法調(diào)用以及增強的時候還需要根據(jù)參數(shù)類型進行匹配菩佑,來最終確定當前調(diào)用的是哪個方法稍坯,Spring在這里將匹配的工作在這里完成匹配的,這樣在后續(xù)調(diào)用的時候變可以直接是我用找到的方法瞧哟,而不需要進行方法的參數(shù)匹配驗證了
- 驗證
在標記的過程中可以對方法存在性進行驗證勤揩,一箭雙雕。
4.1 處理override屬性
beans.factory.support.AbstractBeanFactory(XmlBeanFactory 繼承自這個類凿傅,擁有這個方法)
/**
* 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- 實例化前的的后處理
doCreateBean()方法之前調(diào)用了resolveBeforeInstantiation方法對BeanDefinition中的屬性進行前置處理聪舒。
調(diào)用實例化前處理器進行處理虐急。
短路判斷:如果前置處理返回的結(jié)果不為空止吁,則直接略過后續(xù)Bean的創(chuàng)建而直接返回結(jié)果,這一特性至關重要敬惦,AOP功能就是基于這里的判斷的俄删,如果不為空則調(diào)用初始化后處理器。
實例化的前置處理
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 實例化后的后處理器
@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;
}
實例化前的后處理器的應用
將AbstractBeanDefinition轉(zhuǎn)換為BeanWrapper前的處理斜脂,給子類一個修改BeanDefinition的機會,也就是說當程序經(jīng)過這個方法之后玷或,bean可能已經(jīng)不是我們認為的bean了,而是或許成為一個經(jīng)過處理的代理bean偏友,可能是通過cglib生成的,也可能是通過其他技術生成的,會在AOP中進行講解棱诱,需要清楚的是在bean的實例化前會調(diào)用后處理器的方法進行處理涝动。
初始化后的后處理器
Spring保證bean初始化后盡可能將注冊的后處理器postProcessAfterInitialization方法應用到該bean中。