【Spring原始碼閱讀】 preInstantiateSingletons方法分析,單例Bean獲取/例項化流程
阿新 • • 發佈:2018-12-27
在初始化ClassPathXmlApplicatonContext過程中,核心初始化邏輯在AbstractApplicationContext的refresh函式中:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 供子類拓展,新增建立前必需屬性,校驗如果必需屬性不存在則丟擲MissingRequiredPropertiesException已成
prepareRefresh();
// 呼叫子類實現方法獲取(建立或重新整理)BeanFacotry容器,對於ClassPathXmlApplicationContext,主要呼叫了AbstractRefreshableApplicationContext中實現的方法
// 在這裡,將xml配置檔案中 的Bean解析成了一個個BeanDefinition,建立一個beanName-> beanDefinition 的 map
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 設定類載入器,spel解析器,屬性編輯解析器等,忽略特定介面的依賴註冊(在特定時刻相關Bean再完成注入),註冊一些系統Bean供依賴注入使用。
prepareBeanFactory(beanFactory);
try {
// BeanFactory建立完的後置處理。當前為空實現,供子類拓展
postProcessBeanFactory(beanFactory);
// 呼叫BeanFacotry的相關後置處理器,如果實現了Order相關介面,會先進行排序。
invokeBeanFactoryPostProcessors(beanFactory);
// 註冊相關BeanPostProcessor,供Bean生成前後呼叫。
registerBeanPostProcessors(beanFactory);
// 初始化國際化資訊源
initMessageSource();
// 初始化Spring相關上下文時間廣播器
initApplicationEventMulticaster ();
// 模版方法供子類實現,用於初始化一些特殊Bean配置等
onRefresh();
// 註冊實現了ApplicationListener介面的事件監聽器,用於後續廣播器廣播事件
registerListeners();
// BeanFactory初始化完成時呼叫,初始ConversionService Bean,凍結beanFactory配置,並開始建立BeanFactory中所有非懶載入的單例Bean
finishBeanFactoryInitialization(beanFactory);
// 初始化Lifecycle處理器,呼叫onRefresh方法,廣播ContextRefreshedEvent。
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
其中有一行程式碼,呼叫了finishBeanFactoryInitialization(beanFactory)
。在這一步之前,已經完成了BeanFactory物件初始化、xml配置檔案解析成BeanDefinition、BeanPostProcessor初始化與註冊等操作。
而在完成BeanFactory初始化之時,會初始化容器內所有單例非懶載入物件,供後續業務邏輯進行依賴注入等使用,具體實現在finishBeanFactoryInitialization(beanFactory)
內部的最後一行程式碼:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//…… 省略前面程式碼
// 預例項化所有非懶載入單例Bean
beanFactory.preInstantiateSingletons();
}
具體的preInstantiateSingletons實現如下:
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in " + this);
}
List<String> beanNames;
synchronized (this.beanDefinitionMap) {
// 獲取容器內載入的所有BeanDefinition
beanNames = new ArrayList<String>(this.beanDefinitionNames);
}
// 遍歷初始化所有非懶載入單例Bean
for (String beanName : beanNames) {
// Bean定義公共的抽象類是AbstractBeanDefinition,普通的Bean在Spring載入Bean定義的時候,例項化出來的是GenericBeanDefinition
// 而Spring上下文包括例項化所有Bean用的AbstractBeanDefinition是RootBeanDefinition
// 這時候就使用getMergedLocalBeanDefinition方法做了一次轉化,將非RootBeanDefinition轉換為RootBeanDefinition以供後續操作。
// 注意如果當前BeanDefinition存在父BeanDefinition,會基於父BeanDefinition生成一個RootBeanDefinition,然後再將呼叫OverrideFrom子BeanDefinition的相關屬性覆寫進去。
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 如果Bean不是抽象的,是單例的,不是懶載入的,則開始建立單例物件通過呼叫getBean(beanName)方法初始化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判斷當前Bean是否實現了FactoryBean介面,如果實現了,判斷是否要立即初始化
// 判斷是否需要立即初始化,根據Bean是否實現了SmartFactoryBean並且重寫的內部方法isEagerInit放回true
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
}
// 具體getBean函式實現如下所示:
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
/*
進一步呼叫瞭如下方法,其中有引數:
requiredType=null: 一般情況用不到,如果獲取到的字串,但requiredType是Integer,會在最後進行型別轉換。
args=null: 在獲取prototype物件時傳入,用來初始化原型物件
typeCheckOnly=false: 如果為false,會將Bean標誌為已建立,記錄在alreadyCreated變數中。
*/
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 如果是FactoryBean,會去掉Bean開頭的&符號
// 可能存在傳入別名且別名存在多重對映的情況,這裡會返回最終的名字,如存在多層別名對映A->B->C->D,傳入D,最終會返回A
final String beanName = transformedBeanName(name);
Object bean;
// 這裡先嚐試從快取中獲取,獲取不到再走後面建立的流程
// 獲取到有兩種情況,一種是Bean建立完成儲存到最終的快取中。
// 另一種是未建立完成,但先預存到一個單獨的快取中,這種是針對可能存在迴圈引用的情況的處理。
// 如A引用B,B又引用了A,因而在初始化A時,A會先呼叫建構函式創建出一個例項,在依賴注入B之前,現將A例項快取起來
// 然後在初始化A時,依賴注入階段,會觸發初始化B,B建立後需要依賴注入A時,先從快取中獲取A(這個時候的A是不完整的),避免迴圈依賴的問題出現。
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//這裡主要處理實現了FactoryBean的情況,需要呼叫重寫的getObject()方法來獲取實際的Bean例項。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 原型物件不允許迴圈建立,如果是原型物件則拋異常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果存在父容器,且Bean在父容器中有定義,則通過父容器返回
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
// 進行已建立標記
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 根據名字獲取合併過的對應的RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 檢查mbd是否為抽象的或mbd為單例,但存在args的情況(args只有初始化原型物件才允許存在)
checkMergedBeanDefinition(mbd, beanName, args);
// 確保當前Bean依賴的相關Bean先完成初始化工作
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
}
// 前面獲取失敗,開始建立
if (mbd.isSingleton()) {
// 會先嚐試從快取中獲取,獲取失敗就通過ObjectFactory的createBean方法建立
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
// 建立單例物件
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
//這裡主要處理實現了FactoryBean的情況,需要呼叫重寫的getObject()方法來獲取實際的Bean例項。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 將正在建立的原型物件進行記錄
beforePrototypeCreation(beanName);
// 建立原型物件
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 移除正在建立的原型物件記錄
afterPrototypeCreation(beanName);
}
//這裡主要處理實現了FactoryBean的情況,需要呼叫重寫的getObject()方法來獲取實際的Bean例項。
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 檢查是否為要求的型別,如果不是則嘗試進行型別轉換
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
getSingleton的方法的實現在父類DefaultSingletonBeanRegistry中
// 實現如下:
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 the 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 + "'");
}
// 建立前置檢查,預設實現是記錄當前beanName正在註冊中
beforeSingletonCreation(beanName);
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
// 呼叫簽名定義的內部類進行建立,內部呼叫了createBean(String beanName, RootBeanDefinition mbd, Object[] args)
singletonObject = singletonFactory.getObject();
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 建立前置檢查,預設實現是移除當前beanName正在註冊狀態的記錄
afterSingletonCreation(beanName);
}
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
createBean方法位於AbstractAutowireCapableBeanFactory中,具體實現如下:
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
// 確保對應BeanClass完成解析,具體表現是進行了ClassLoder.loadClass或Class.forName完成了類載入
resolveBeanClass(mbd, beanName);
try {
// 準備方法覆蓋,主要為lookup-method,replace-method等配置準備
mbd.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 供特定後置處理器拓展,如果直接生成了一個Bean,就直接返回不走正常建立流程。
// 具體邏輯是判斷當前Spring容器是否註冊了實現了InstantiationAwareBeanPostProcessor介面的後置處理器
// 如果有,則依次呼叫其中的applyBeanPostProcessorsBeforeInstantiation方法,如果中間任意一個方法返回不為null,直接結束呼叫。
// 然後依次所有註冊的BeanPostProcessor的postProcessAfterInitialization方法(同樣如果任意一次返回不為null,即終止呼叫。
Object bean = resolveBeforeInstantiation(beanName, mbd);
// 如果不為空,說明提前生成了例項,直接返回
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 具體建立Bean邏輯
Object beanInstance = doCreateBean(beanName, mbd, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
具體建立Bean的邏輯如下所示:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// BeanWrapper封裝了具體的Bean例項,然後可以很方便地通過呼叫getPropertyValue和setPropertyValue等方法反射讀寫Bean的具體屬性
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 先嚐試從快取中取
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 呼叫構造方法建立一個空例項物件,並用BeanWrapper進行包裝
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null)