本篇分析Spring如何加載bean的實例,
從ClassPathXmlApplicationContext的getBean開始分析
//抽象方法
Object getBean(String var1) throws BeansException;
public Object getBean(String name) throws BeansException {
this.assertBeanFactoryActive();
return this.getBeanFactory().getBean(name);
}
會進入BeanFactory接口的getBean,根據繼承圖找到AbstractApplicationContext的getBean方法
上篇文章Spring IOC實現原理筆記(二) – 加載XML配置提過,ClassPathXmlApplicationContext中的BeanFactory成員實際是DefaultListableBeanFactory
public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = this.transformedBeanName(name);
//【標記1】嘗試獲取
Object sharedInstance = this.getSingleton(beanName);//
Object bean;
if(sharedInstance != null && args == null) {
...
//返回對應的實例,有時候存在諸如BeanFactory的情況並不是直接返回實例本身
//而是返回指定方法返回的實例
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
//原型模式(Prototype)下存在循環依賴,不能解決(因爲原型模式是直接創建新的實例的)
if(this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
...如果父BeanFactory不爲空,並且當前沒有相應bean的
BeanDefinition,那就交由父BeanFactory加載bean,並返回。
if(!typeCheckOnly) {
this.markBeanAsCreated(beanName);//標誌當前bean已經創建
}
try {
//將存儲XML配置文件的GenericBeanDefinition轉換爲RootBeanDefinition
final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
String[] var11;
if(dependsOn != null) {
for(String dependsOnBean:dependsOn) {
String dependsOnBean = var11[var13];
if(this.isDependent(beanName, dependsOnBean)) {
...說明有循環依賴,要報異常(構造方法注入循環依賴)
}
//這裏記錄要創建的依賴的bean,用於循環依賴檢測
this.registerDependentBean(dependsOnBean, beanName);
//遞歸實例化依賴的bean
this.getBean(dependsOnBean);
}
}
if(mbd.isSingleton()) {//單例模式
//【標記2】
sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
//【標記3】
return this.createBean(beanName, mbd, args);//真正創建實例
} catch (BeansException var2) {
this.destroySingleton(beanName);
throw var2;
}
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else ...省略其他模式
} catch (BeansException var23) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var23;
}
}
if(requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
//對應類型的轉換
return this.getTypeConverter().convertIfNecessary(bean, requiredType);
...
} else {
return bean;
}
}
獲取bean實例時,首先嚐試獲取單例(對應上面【標記1】)
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//嘗試從緩存池中獲取
Object singletonObject = this.singletonObjects.get(beanName);
if(singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
//獲取不到,但正在創建
synchronized(this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
//如果此bean不是正在加載且允許提前引用
if(singletonObject == null && allowEarlyReference) {
//當某些方法需要提前初始化的時候,會調用addSingletonFactory方法,
//將對應的ObjectFactory初始化策略存儲在singletonFactories
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if(singletonFactory != null) {
//調用預設定的getObject方法
singletonObject = singletonFactory.getObject();
//記錄緩存中
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject != NULL_OBJECT?singletonObject:null;
}
獲取單例bean:(對應【標記2】)
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
...
synchronized(this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if(singletonObject == null) {
...
//把beanName放入singletonsCurrentlyInCreation
this.beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = this.suppressedExceptions == null;
if(recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
//調用工廠的getObject方法獲取實例
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch ...
} finally {
...
//把beanName從singletonsCurrentlyInCreation移除
this.afterSingletonCreation(beanName);
}
if(newSingleton) {
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject != NULL_OBJECT?singletonObject:null;
}
}
//把beanName緩存到singletonsCurrentlyInCreation,對應的isSingletonCurrentlyInCreation方法會返回true
protected void beforeSingletonCreation(String beanName) {
if(!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
//把beanName從singletonsCurrentlyInCreation移除
protected void afterSingletonCreation(String beanName) {
if(!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
ObjectFactory工廠的getObject方法實現調用的是createBean方法(對應【標記3】)
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
...
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if(resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
...
//驗證及準備覆蓋的方法
mbdToUse.prepareMethodOverrides();
...
Object beanInstance;
...
//給BeanPostProcessors(需要是InstantiationAwareBeanPostProcessor的實例)機會返回代理來代替真正的實例(AOP實現就用這)
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if(beanInstance != null) {
return beanInstance;
}
...
//真正創建bean實例
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
...
return beanInstance;
}
真正創建bean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) {
BeanWrapper instanceWrapper = null;
if(mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if(instanceWrapper == null) {
//【標記4】根據指定bean使用對應的策略創建新的實例,如工廠方法,構造函數自動注入,簡單初始化
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper != null?instanceWrapper.getWrappedInstance():null;
Class<?> beanType = instanceWrapper != null?instanceWrapper.getWrappedClass():null;
synchronized(mbd.postProcessingLock) {
if(!mbd.postProcessed) {
//應用MergedBeanDefinitionPostProcessor
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
//是否需要提早曝光:單例&允許循環依賴&當前bean正在創建中,檢查循環依賴
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if(earlySingletonExposure) {
...
//爲避免後期循環依賴,可以在bean初始化完成前將創建實例的ObjectFactory工廠加入工廠
this.addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
//對bean再一次依賴應用,主要應用SmartInstantiationAwareBeanPostProcessor
//AOP就是在這裏將advice動態織入bean中,沒有就直接返回bean,不做處理
return this.getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
//【標記5】對bean進行填充,將各個屬性值注入,其中可能存在依賴於其他bean的屬性,則會遞歸初始依賴的bean
this.populateBean(beanName, mbd, instanceWrapper);
if(exposedObject != null) {
//【標記6】調用初始化方法,如init-method,InitializingBean的afterPropertiesSet
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
}
} catch...
if(earlySingletonExposure) {
Object earlySingletonReference = this.getSingleton(beanName, false);
//只有在檢測到有循環依賴的情況下才會不會空
if(earlySingletonReference != null) {
if(exposedObject == bean) {
//沒有在初始化方法中被改變(即沒有被增強)
exposedObject = earlySingletonReference;
} else if(!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
for(String dependentBean:dependentBeans) {
//檢測依賴,bean實例化後,其依賴的bean也需要被實例化
if(!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if(!actualDependentBeans.isEmpty()) {
...存在循環依賴
}
}
}
}
try {
//根據scope註冊bean
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch ...
}
單例的循環依賴解決:如果是在構造函數循環依賴那解決不了;如果是通過setter方法的循環依賴,那會調addSingletonFactory加入一個ObjectFactory,其getObject實現會返回一個實例引用來解決循環依賴
根據指定bean使用對應的策略創建新的實例(對應【標記4】)
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if(beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
...非公開類
} else if(mbd.getFactoryMethodName() != null) {
//如果工廠方法不爲空則使用工廠方法初始化策略
return this.instantiateUsingFactoryMethod(beanName, mbd, args);
} else {
boolean resolved = false;
boolean autowireNecessary = false;
if(args == null) {
synchronized(mbd.constructorArgumentLock) {
//一個類有多個構造函數,每個構造函數都有不同的參數,所以調用前根據參數鎖定構造函數或對應的工廠方法
if(mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//如果已經解析過則使用解析好的構造函數
if(resolved) {
//autowireNecessary爲true則用構造函數自動注入,否則使用默認構造函數構造
return autowireNecessary?this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null):this.instantiateBean(beanName, mbd);
} else {
//根據參數解析構造函數
Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
//ctors爲空就用默認構造函數,否則使用用構造函數自動注入
return ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)?this.instantiateBean(beanName, mbd):this.autowireConstructor(beanName, mbd, ctors, args);
}
}
}
根據參數解析構造函數邏輯很複雜,因爲有很多不確定性;而使用默認構造方法實例化則會分兩種情況:第一種,beanDefinition的getMethodOverrides方法返回空(即沒有使用replace或lookup配置),那就直接使用反射。第二種,使用CGlib進行動態代理,覆蓋或動態替換方法
上面實例化的bean,接着就是對bean進行屬性填充,看populateBean方法(對用【標記5】)
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
if(bw == null) {
if(!((PropertyValues)pvs).isEmpty()) {
...空對象不能填充屬性
}
} else {
//給InstantiationAwareBeanPostProcessors最後一次機會在屬性設置前改變bean
boolean continueWithPropertyPopulation = true;
if(!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Iterator it = this.getBeanPostProcessors().iterator();
while(it.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)it.next();
if(bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
if(!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
//continueWithPropertyPopulation爲true,說明InstantiationAwareBeanPostProcessors沒有中斷屬性注入
if(continueWithPropertyPopulation) {
if(mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {
MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
//根據名稱自動注入
if(mbd.getResolvedAutowireMode() == 1) {
this.autowireByName(beanName, mbd, bw, newPvs);
}
//根據類型自動注入
if(mbd.getResolvedAutowireMode() == 2) {
this.autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
//依賴檢查
boolean needsDepCheck = mbd.getDependencyCheck() != 0;
if(hasInstAwareBpps || needsDepCheck) {
//調用InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法
PropertyDescriptor[] filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if(hasInstAwareBpps) {
Iterator it = this.getBeanPostProcessors().iterator();
while(it.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)it.next();
if(bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
pvs = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
if(pvs == null) {
return;
}
}
}
}
if(needsDepCheck) {
this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
}
}
//將屬性應用到bean中
this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
}
}
}
填充好bean的屬性後,會調用initializeBean方法會對各種aware等接口進行調用(對應【標記6】)
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
...
this.invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if(mbd == null || !mbd.isSynthetic()) {
//調用BeanPostProcessors的postProcessBeforeInitialization
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
//調用init-method,InitializingBean的afterPropertiesSet
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch...
if(mbd == null || !mbd.isSynthetic()) {
//調用BeanPostProcessors的postProcessAfterInitialization
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
Spring IOC實現原理筆記(一)這篇中的例子輸出結果可以在從上面裏驗證了
大致總結bean實例的加載流程:
• 嘗試從單例緩存池中取,成功的話返回進行實際需要的實例(如在beanName前加&可以得到該bean的beanFactory)
• 單例緩存池取不到則進行實例化,需要判斷能否解決循環引用,不同的scope不同地生命週期。
• 進行實例化前,如果工廠方法不爲空則使用工廠方法初始化策略;否則可以通過InstantiationAwareBeanPostProcessor來實例化(AOP藉此實現),如果InstantiationAwareBeanPostProcessor返回實例化對象不爲空那就直接返回。
• InstantiationAwareBeanPostProcessor沒返回實例,則繼續進行bean實例操作,解析構造函數,用其進行反射實例化或CGlib代理實例化
• 實例化後,對實例進行屬性填充,填充前還會最後一次交由InstantiationAwareBeanPostProcessor決定是否繼續填充,
• 填充完屬性,還會讓InstantiationAwareBeanPostProcessor進行屬性檢驗,接着就進行對各種Aware接口,init-method等進行調用
• 最後註冊DisposeableBean,用戶可通過配置屬性destroy-method方法後之策後處理器DestructAwareBeanPostProcessor來統一處理bean的銷燬方法
參考:
Spring源碼(4.2.2.RELEASE)
《Spring源碼深度解析》