一坤塞、概述
spring初始化Bean的流程比較復雜,除了普通的構造函數(shù)實例化Bean之外澈蚌,spring還支持工廠模式創(chuàng)建Bean(即常說的Factory Bean)摹芙。在spring實例化完Bean之后,會進行Bean的一些初始化工作宛瞄。其中涉及到擴展點調(diào)用浮禾、運行時類型成員解析、依賴注入份汗、懶加載等流程盈电,還解決了循環(huán)引用、類型轉(zhuǎn)換等問題裸影。熟悉Bean加載的過程挣轨,開發(fā)過程中選擇擴展點時就可以做到游刃有余。為了更加關注邏輯流程轩猩,本文所貼的代碼精簡掉了不相關的部分卷扮。
二荡澎、Bean實例化概要流程
1.獲取Bean過程中涉及到的擴展點
org.springframework.beans.factory.support.MethodOverride
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor
org.springframework.beans.factory.config.BeanPostProcessor
org.springframework.beans.factory.InitializingBean
2.關鍵方法框架圖
三、Bean實例化詳細流程
1.相關入口
- 根據(jù)類型獲取Bean
org.springframework.context.support.AbstractApplicationContext.getBean(Class<T>)- 根據(jù)名字獲取Bean
org.springframework.context.support.AbstractApplicationContext.getBean(String)- 實際獲取Bean
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean- 根據(jù)給出的Bean獲取真實Bean(可能是factoryBean)
org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance- 創(chuàng)建Bean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean- 實際創(chuàng)建Bean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean
2.詳細解析
除了單例且非懶加載的Bean是在ApplicationContext刷新的時候初始化之外晤锹。其他Bean都是在使用的時候才會加載摩幔,即我們常用的getBean方法。這個方法提供了很多重載鞭铆,總的類型只有兩種:
- 根據(jù)類型獲取Bean
- 根據(jù)Name獲取Bean
兩種類型最終內(nèi)部都調(diào)用到了同一個方法或衡,詳見下述偽代碼:
-------------------- 根據(jù)類型獲取Bean最終調(diào)用的是doGetBean方法
-- org.springframework.context.support.AbstractApplicationContext
public <T> T getBean(Class<T> requiredType) throws BeansException {
return getBeanFactory().getBean(requiredType);
}
-- org.springframework.beans.factory.support.DefaultListableBeanFactory
public <T> T getBean(Class<T> requiredType) throws BeansException {
return getBean(requiredType, (Object[]) null);
}
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
String[] beanNames = getBeanNamesForType(requiredType);
if (beanNames.length == 1) {
return getBean(beanNames[0], requiredType, args);
}
}
-- org.springframework.beans.factory.support.AbstractBeanFactory.getBean
public <T> T getBean(String name, Class<T> requiredType, Object[] args) throws BeansException {
return doGetBean(name, requiredType, args, false);
}
-------------------- 根據(jù)名字獲取Bean最終調(diào)用的也是doGetBean方法
-- org.springframework.context.support.AbstractApplicationContext
public Object getBean(String name) throws BeansException {
return getBeanFactory().getBean(name);
}
-- org.springframework.beans.factory.support.AbstractBeanFactory
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
doGetBean方法中很多地方都會調(diào)用getObjectForBeanInstance來獲取最終需要的bean。該方法是spring為實現(xiàn)FactoryBean而編寫的车遂,其內(nèi)部判斷了是否需要利用工廠模式來創(chuàng)建出目標bean封断,詳細偽代碼如下:
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
-- 如果對象不是一個FactoryBean或者這里就是要取FactoryBean,則直接返回
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
-- 如果對象是一個FactoryBean且這里要獲取對應的Bean舶担,則嘗試從factoryBean已創(chuàng)建的對象緩存中獲取
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
-- 緩存中沒有則用Factory去創(chuàng)建出Bean
if (object == null) {
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
-- org.springframework.beans.factory.support.FactoryBeanRegistrySupport
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
Object object = doGetObjectFromFactoryBean(factory, beanName);
object = postProcessObjectFromFactoryBean(object, beanName);
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
return (object != NULL_OBJECT ? object : null);
}
-- doGetObjectFromFactoryBean中關鍵代碼
object = factory.getObject();
return object;
如果factory緩存中沒有需要的Bean時坡疼,不管是單例Bean、模板Bean衣陶,最終都會調(diào)用createBean方法來創(chuàng)建一個Bean柄瑰,并調(diào)用getObjectForBeanInstance方法確定目標bean。createBean內(nèi)部會調(diào)用doCreateBean方法進行對象的創(chuàng)建剪况、初始化等工作教沾,詳細偽代碼如下:
-- doGetBean
Object bean = createBean(beanName, mbd, args);
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
-- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
resolveBeanClass(mbd, beanName);
mbd.prepareMethodOverrides();
Object bean = resolveBeforeInstantiation(beanName, mbd);
if (bean != null) {
return bean;
}
Object beanInstance = doCreateBean(beanName, mbd, args);
return beanInstance;
}
-- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// 創(chuàng)建目標對象,包裝成BeanWrapper
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
// 執(zhí)行MergedBeanDefinitionPostProcessor接口
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
//將單例添加到Bean工廠的緩存中译断,解決循環(huán)引用問題
...
// 成員變量初始化
populateBean(beanName, mbd, instanceWrapper);
Object exposedObject = initializeBean(beanName, bean, mbd);
//實例化它依賴的Bean
...
//如果這個Bean是可銷毀的Bean授翻,則注冊到factory中。
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
}
populateBean和initializeBean完成了Bean的成員變量初始化工作镐作。其中藏姐,populateBean方法在屬性設置之前調(diào)用了InstantiationAwareBeanPostProcessor隆箩,允許實現(xiàn)自定義方式的屬性注入该贾。之后把依賴的非簡單類型取出依賴注入(有set方法的這種)。再把所有屬性在類型轉(zhuǎn)換器走一次捌臊,設置到Bean中(applyPropertyValues)杨蛋。
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
//調(diào)用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法,
ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)
if (...) { //允許InstantiationAwareBeanPostProcessor終止初始化流程
return;
}
//根據(jù)類型或者名字調(diào)用setXXX方法自動注入
autowireByXXX(beanName, mbd, bw, newPvs);
//成員被自動注入后理澎,調(diào)用InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
//解析所有運行時的引用逞力,應用所有的屬性值(包含類型轉(zhuǎn)換)。
applyPropertyValues(beanName, mbd, bw, pvs);
}
initializeBean調(diào)用了些Aware方法:
- BeanNameAware
- BeanClassLoaderAware
- BeanFactoryAware
調(diào)用BeanPostProcessor的postProcessBeforeInitialization方法(例如ApplicationContextAware)糠爬。如果Bean實現(xiàn)了InitializingBean寇荧,則調(diào)用它的afterPropertiesSet方法。調(diào)用Bean設置的initMethod方法执隧,調(diào)用BeanPostProcessor的postProcessAfterInitialization方法揩抡。詳細的偽代碼如下:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
//包含InitializingBean的方法和自定義的init方法
invokeInitMethods(beanName, wrappedBean, mbd);
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
四户侥、總結
spring實例化Bean過程,提供了許多擴展點峦嗤。其Factory Bean模式也是通過getBean方法內(nèi)部做了特殊處理才實現(xiàn)的蕊唐。在Bean被實例化之前,會調(diào)用MergedBeanDefinitionPostProcessor進行預處理烁设,給予了我們對對象進行代理的機會替梨,使其不去創(chuàng)建具體的目標類型對象。在配置文件加載前装黑、加載后副瀑,spring都提供了可供我們添加邏輯的接口,來實現(xiàn)自己的增強功能恋谭。
對ApplicationContext初始化流程不熟悉的話俗扇,可以參考這篇文章:spring擴展之a(chǎn)pplication context初始化流程