Spring IOC容器bean初始化原始碼分析
上一篇分析對bean定義的解析原始碼進行了分析,這個過程的最終結果是把xml檔案中bean的定義解析成一個個的BeanDefinition物件並且註冊到容器中,在Spring IOC容器啟動簡介篇中分析,在容器啟動的最後會對容器中的所有bean進行初始化,利用之前解析出的BeanDefinition物件,建立一個個最終的bean物件,並且完成bean之間的依賴注入,本篇從原始碼的角度分析在容器啟動時所有bean的初始化過程,bean初始化的粗略序列圖如下:
按照作用域劃分bean有如下幾個作用域
singleton
prototype
自定義作用域
關於bean的初始化,幾種作用域的bean基本上是相同的,所以下面主要分析singleton作用域bean初始化,可能會稍微提到其它作用域。
合併BeanDefinition
遍歷所有已經註冊到容器中的bean名稱,因為在bean定義解析完成之後所有解析出的bean名稱和bean名稱和BeanDefinition之間的對映關係都已經註冊到容器中,所以根據bean名稱可以定位到響應的BeanDefinition,定位到BeanDefinition之後,接下來需要合併BeanDefinition,因為bean定義中可能會有parent屬性表示該bean繼承某個bean,所有要把父bean的一些屬性拷貝到子bean中,程式碼在AbstractBeanDefinition中,該方法會把當前bean定義中一些屬性複製到other bean定義中。
bean定義合併完成之後生成一個RootBeanDefinition物件返回給容器。如果bean沒有繼承其它的bean,那麼把原始的BeanDefinition封裝到RootBeanDefinition物件中返回給容器。public void overrideFrom(BeanDefinition other) { if (StringUtils.hasLength(other.getBeanClassName())) { setBeanClassName(other.getBeanClassName()); } if (StringUtils.hasLength(other.getFactoryBeanName())) { setFactoryBeanName(other.getFactoryBeanName()); } if (StringUtils.hasLength(other.getFactoryMethodName())) { setFactoryMethodName(other.getFactoryMethodName()); } if (StringUtils.hasLength(other.getScope())) { setScope(other.getScope()); } setAbstract(other.isAbstract()); setLazyInit(other.isLazyInit()); setRole(other.getRole()); getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues()); getPropertyValues().addPropertyValues(other.getPropertyValues()); setSource(other.getSource()); copyAttributesFrom(other); if (other instanceof AbstractBeanDefinition) { AbstractBeanDefinition otherAbd = (AbstractBeanDefinition) other; if (otherAbd.hasBeanClass()) { setBeanClass(otherAbd.getBeanClass()); } setAutowireCandidate(otherAbd.isAutowireCandidate()); setAutowireMode(otherAbd.getAutowireMode()); copyQualifiersFrom(otherAbd); setPrimary(otherAbd.isPrimary()); setDependencyCheck(otherAbd.getDependencyCheck()); setDependsOn(otherAbd.getDependsOn()); setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed()); setLenientConstructorResolution(otherAbd.isLenientConstructorResolution()); if (StringUtils.hasLength(otherAbd.getInitMethodName())) { setInitMethodName(otherAbd.getInitMethodName()); setEnforceInitMethod(otherAbd.isEnforceInitMethod()); } if (StringUtils.hasLength(otherAbd.getDestroyMethodName())) { setDestroyMethodName(otherAbd.getDestroyMethodName()); setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod()); } getMethodOverrides().addOverrides(otherAbd.getMethodOverrides()); setSynthetic(otherAbd.isSynthetic()); setResource(otherAbd.getResource()); } else { setResourceDescription(other.getResourceDescription()); } }
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
...
if (mbd == null) {
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
...
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}
...
}
return mbd;
}
}
區分工廠bean
容器啟動時會初始化所有非抽象並且非懶載入的單例bean,接下來區分bean的型別是不是FactoryBean,FactoryBean比較特殊,因為FactoryBean是用來生成其它bean的,所以如果在容器中定義了FactoryBean時,通過該FactoryBean的id或別名獲取的不是FactoryBean本身而是它生產的bean,觸發FactoryBean.getObject方法,並且預設情況下FactoryBean.getObject不會被提前觸發必須通過應用層呼叫觸發,容器中的處理是,如果bean是FactoryBean,通過在beanName前加上&符號讓容器初始化FactoryBean的真正例項,並且判斷該FactoryBean的目標bean是否需要提前初始化,預設情況下時不需要,但是可以通過SmartFactoryBean介面來進行擴充套件,如果需要初始化,呼叫bean的初始化bean例項getBean方法。如果bean是普通的bean直接呼叫bean的初始化getBean方法,程式碼在DefaultListableBeanFactory的preInstantiateSingletons方法中:
public void preInstantiateSingletons() throws BeansException {
...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
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);
}
}
}
}
獲取bean例項
無論是容器啟動觸發的bean初始化還是應用層觸發的bean初始化,程式碼都是重用的,都是通過getBean方法獲取bean的例項,獲取bean例項時先檢查bean是否已經例項化過並且註冊到容器中了,包括兩種情況:
- 所有初始化操作已經完成,所有bean的依賴關係已經注入。
- 提前暴露的bean,這種bean的某些依賴關係還沒有注入完成,之所以出現這種情況是因為bean存在迴圈依賴,為了避免死迴圈需要提前暴露bean的例項,通過ObjectFactory.getObject建立bean例項。
如果bean已經被例項化過直接使用該bean,程式碼在DefaultSingletonBeanRegistry類的getSingleton方法,所有初始化完成的bean儲存在singletonObjects雜湊表中,提前暴露的bean儲存在earlySingletonObjects雜湊表中。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
如果bean沒有例項化過,執行bean的例項化初始化,如果bean的作用域時prototype並且和其它bean發生了迴圈引用,初始化失敗丟擲BeanCurrentlyInCreationException異常。
因為填充bean的屬性時,如果bean的屬性也引用了一個bean,那麼此時同樣也會觸發getBean方法,如果當前引用的bean在當前容器中不存在,那麼把初始化該bean的動過委託給父容器,也就是從父容器中查詢這個bean,比如屬性的引用標籤是<ref parent="xxxx">這種形式時,那麼初始化xxxx這個bean的動過只能交給父容器。相關程式碼片段在AbstractBeanFactory的doGetBean方法中:
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
...
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
...
}
else {
...
// Check if bean definition exists in this factory.
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);
}
}
...
}
...
return (T) bean;
}
如果bean是當前容器的bean,那麼繼續初始化邏輯,在初始化之前先給bean打上標記,標識當前bean已經被建立,標識資訊存在alreadyCreated雜湊表中。校驗bean定義,是否是抽象bean,或者傳了arg引數但是bean不是prototype,當需要根據動態引數例項化bean時,該bean的作用域只能是prototype。
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, Object[] args)
throws BeanDefinitionStoreException {
// check if bean definition is not abstract
if (mbd.isAbstract()) {
throw new BeanIsAbstractException(beanName);
}
// Check validity of the usage of the args parameter. This can
// only be used for prototypes constructed via a factory method.
if (args != null && !mbd.isPrototype()) {
throw new BeanDefinitionStoreException(
"Can only specify arguments for the getBean method when referring to a prototype bean definition");
}
}
檢查當前bean是否有依賴的bean,也就是說bean是否定義了depends-on屬性,如果有的話先初始化這些依賴bean,並且註冊bean的依賴關係到容器中,包含兩個結構,一個是bean的依賴列表dependentBeanMap,另一個是bean的被依賴列表dependenciesForBeanMap,儲存dependentBeanMap的目的是在銷燬該bean時直接遍歷該雜湊表把所有依賴的bean都銷燬掉,dependenciesForBeanMap這個結構目前還沒有發現有什麼用途,相關程式碼片段如下:
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
...
try {
...
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
}
...
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
...
return (T) bean;
}
建立bean例項
檢查當前是否正在銷燬所有的單例bean,如果是的話報錯丟擲BeanCreationNotAllowedException異常,只有等銷燬操作完成之後才能進行bean初始化動作。
儲存標記到singletonsCurrentlyInCreation雜湊表中標識bean正在被建立,這個標識將會被用來處理迴圈引用。接下來建立bean例項,對Class、MethodOverride做一些準備處理,然後進行例項化前處理操作,檢查容器中的所有BPP(BeanPostProcessor)中是否有實現了InstantiationAwareBeanPostProcessor介面的,如果有的話觸發它的postProcessBeforeInstantiation方法看看該方法是否產生了非空的bean例項,如果有的話中斷BPP的遍歷,繼續遍歷觸發BPP的postProcessAfterInitialization方法,如果有BPP返回了null例項,中斷遍歷,程式碼在AbstractAutowireCapableBeanFactory類:
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.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
throws BeansException {
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;
}
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;
}
如果上述前處理中產生了非空的bean,例項初始化結束直接返回,這一步非常重要,AOP就是利用這個過程偷樑換柱把bean例項換成bean的代理物件。如果沒有BPP攔截bean的例項化,那麼進入bean真正的例項化過程:
首先例項化bean,例項化有幾種方式:
- 工廠方法
- 自定義構造子
- 預設構造子
檢查bean是否定義了factory-method,如果有factory-method使用該工廠方法例項化bean,存在兩種方式,一種是定義factory-bean,通過指定的其它bean的非靜態方法初始化該bean;另一種是定義class,通過該class的靜態方法例項化該bean,此時factory-method必須是靜態方法。如果工廠方法中有引數,那麼會在工廠方法引數和構造子引數之間進行匹配,這種情況下目標bean的作用域必須是prototype,應用程式碼在呼叫getBean向容器請求bean例項時必須要傳入相應的引數,下面是個簡單的例子:
類定義:
public class ItemFactory {
public ItemBean getItem(String name) {
ItemBean item = new ItemBean(name);
return item;
}
}
public class ItemBean {
private String name;
public ItemBean(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
bean定義:
<bean id="factory" class="spring.beans.factory.ItemFactory">
</bean>
<bean id="item1" factory-bean="factory" factory-method="getItem"
scope="prototype">
<constructor-arg value="name1"></constructor-arg>
</bean>
呼叫程式碼:ApplicationContext ctx = new ClassPathXmlApplicationContext(
"spring/beans/factory/factory.xml");
ItemBean item = (ItemBean) ctx.getBean("item1", "name11");
工廠方法例項化bean的邏輯在ConstructorResolver類的instantiateUsingFactoryMethod方法中,這裡因為是singleton作用域的bean例項化,所以不會涉及到工廠方法的引數處理,args引數是null值。
如果bean定義為構造子注入或者裝配模式是構造子,那麼通過自定義構造子例項化bean並且完成構造子相關的依賴注入,如果沒有定義工廠方法factory-method,檢查自定義了構造子,完成構造子依賴注入的程式碼在ConstructorResolver類的autowireConstructor方法中,這個方法完成的功能是,解析出構造子和構造子引數,並對引數求值,如果出現了EL表示式對EL表示進行解析並且計算出結果,根據結果值的型別求對應的值,如果是引用型別那麼首先例項化被引用的bean,呼叫BeanFactory的getBean,如果是字元型別那麼根據引數的實際型別轉換成對應的值,需要藉助PropertyEditor,程式碼片段如下:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
...
// Need to determine the constructor...
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
...
}
框架使用BeanWrapper來封裝例項化的bean,在autowireConstructor方法的開始呼叫了initBeanWrapper方法,來看看這個方法:
protected void initBeanWrapper(BeanWrapper bw) {
bw.setConversionService(getConversionService());
registerCustomEditors(bw);
}
protected void registerCustomEditors(PropertyEditorRegistry registry) {
PropertyEditorRegistrySupport registrySupport =
(registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
if (registrySupport != null) {
registrySupport.useConfigValueEditors();
}
if (!this.propertyEditorRegistrars.isEmpty()) {
for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
try {
registrar.registerCustomEditors(registry);
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
if (isCurrentlyInCreation(bce.getBeanName())) {
if (logger.isDebugEnabled()) {
logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() +
"] failed because it tried to obtain currently created bean '" +
ex.getBeanName() + "': " + ex.getMessage());
}
onSuppressedException(ex);
continue;
}
}
throw ex;
}
}
}
if (!this.customEditors.isEmpty()) {
for (Map.Entry<Class<?>, Class<? extends PropertyEditor>> entry : this.customEditors.entrySet()) {
Class<?> requiredType = entry.getKey();
Class<? extends PropertyEditor> editorClass = entry.getValue();
registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass));
}
}
}
這個方法的功能是把容器中預設的PropertyEditor和註冊到容器中的自定義PropertyEditor複製到BeanWrapper中,來輔助構造子注入時的值轉換操作以及為後面其它屬性的注入值轉換做準備,為什麼要把這些PropertyEditor複製到各個BeanWrapper中?我的理解是,PropertyEditor是有狀態非執行緒安全的,每個BeanWrapper複製一份可以消除高併發下的狀態同步開銷。上面提到的instantiateUsingFactoryMethod方法功能也類似,只不過instantiateUsingFactoryMethod是要解析工廠方法和引數,如果工廠方法是非靜態的那麼會多一步例項化工廠方法所在的bean。
無論是構造子還是工廠方法,在解析完之後都會把處理結果儲存下來,RootBeanDefinition中有兩個屬性resolvedConstructorOrFactoryMethod和constructorArgumentsResolved,分別用來儲存之前解析出的構造子/工廠方法和引數,下次在處理同樣的bean時可以直接複用之前的解析結果,快取程式碼在ArgumentsHolder類的storeCache方法中:
public void storeCache(RootBeanDefinition mbd, Object constructorOrFactoryMethod) {
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
mbd.constructorArgumentsResolved = true;
if (this.resolveNecessary) {
mbd.preparedConstructorArguments = this.preparedArguments;
}
else {
mbd.resolvedConstructorArguments = this.arguments;
}
}
}
如果即沒有工廠方法又沒有自定義構造子,那麼使用預設構造子例項化bean,進入AbstractAutowireCapableBeanFactory的instantiateBean方法,例項化過程時序圖如下:
SimpleInstantiationStrategy建立bean例項,首先檢查bean是否定義了方法覆蓋(lookup-method或replaced-method),如果未定義方法覆蓋那麼直接建立bean對應的class的例項。如果定義了方法覆蓋,那麼會使用CGLIB動態的生成class的一個子類,建立該子類的物件作為bean例項,下面兩個內部類是lookup-method和replaced-method的CGLIB回撥,從程式碼中可以看到當呼叫被lookup-mothod覆蓋的方法時,會從容器中獲取一個bean返回,而呼叫被replaced-method覆蓋的方法時會呼叫MethodReplacer介面替換實現:
/**
* CGLIB MethodInterceptor to override methods, replacing them with an
* implementation that returns a bean looked up in the container.
*/
private class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
// Cast is safe, as CallbackFilter filters are used selectively.
LookupOverride lo = (LookupOverride) beanDefinition.getMethodOverrides().getOverride(method);
return owner.getBean(lo.getBeanName());
}
}
/**
* CGLIB MethodInterceptor to override methods, replacing them with a call
* to a generic MethodReplacer.
*/
private class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
ReplaceOverride ro = (ReplaceOverride) beanDefinition.getMethodOverrides().getOverride(method);
// TODO could cache if a singleton for minor performance optimization
MethodReplacer mr = (MethodReplacer) owner.getBean(ro.getMethodReplacerBeanName());
return mr.reimplement(obj, method, args);
}
}
例項建立成功之後,把建立好的例項封裝到BeanWrapper中,並且呼叫initBeanWrapper方法把PropertyEditor都新增到BeanWrapper中為後面的屬性值轉換做準備。接下來觸發所有BPP的擴充套件MergedBeanDefinitionPostProcessor,挨個呼叫它們的postProcessMergedBeanDefinition方法。
檢查是否發生了迴圈引用,如果存在迴圈引用提前快取例項到容器中,程式碼片段在AbstractAutowireCapableBeanFactory類的doCreateBean方法中:
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
在getEarlyBeanReference方法中會觸發SmartInstantiationAwareBeanPostProcessor,可以在這一步把bean換掉,AOP就是在這裡把Bean換成代理的。
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
if (exposedObject == null) {
return exposedObject;
}
}
}
}
return exposedObject;
}
注入bean屬性
接下來是填充bean的屬性,在屬性填充之前先檢查是否有自定義的InstantiationAwareBeanPostProcessor的實現的postProcessAfterInstantiation方法返回了false,如果有跳過屬性填充,這個特性可以被用來實現屬性注入。如果bean設定了自動裝配,則處理自動裝配:
下面程式碼是byName模式的處理,從程式碼中可以看出,遍歷所有屬性,從容器中獲取和屬性名稱相同的bean並且新增到PropertyValues結構中,並且呼叫registerDependentBean註冊依賴關係:
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
下面程式碼是byType模式的處理,首先通過屬性名稱查找出對應的set方法,然後根據set方法中的引數型別向容器獲取對應的bean,獲取到的bean新增到
PropertyValues結構中,並且呼叫registerDependentBean註冊依賴關係:
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
if (!Object.class.equals(pd.getPropertyType())) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
觸發容器中註冊的InstantiationAwareBeanPostProcessor,呼叫它們的postProcessPropertyValues方法,如果當有返回null值的,那麼填充過程結束。
檢查bean是否設定了依賴模式(dependency-check),如果設定的依賴模式非none,那麼進行依賴檢查,當bean定義的property屬性在對應的class中既沒有相應的設值方法,也沒有相對應的屬性名時不同的模式處理如下:
- none:不檢查
- simple:如果該屬性型別是簡單型別或陣列型別,丟擲異常UnsatisfiedDependencyException
- object:如果該屬性型別是複雜引用型別,丟擲異常UnsatisfiedDependencyException
- all:所有型別都丟擲異常UnsatisfiedDependencyException
相關程式碼在AbstractAutowireCapableBeanFactory類的checkDependencies方法中:
protected void checkDependencies(
String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, PropertyValues pvs)
throws UnsatisfiedDependencyException {
int dependencyCheck = mbd.getDependencyCheck();
for (PropertyDescriptor pd : pds) {
if (pd.getWriteMethod() != null && !pvs.contains(pd.getName())) {
boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType());
boolean unsatisfied = (dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_ALL) ||
(isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
(!isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
if (unsatisfied) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, pd.getName(),
"Set this property value or disable dependency checking for this bean.");
}
}
}
}
依賴檢查完成之後,把bean定義中所有的property,即BeanDefinition中的PropertyValue結構這隻到BeanWrapper中,呼叫BeanWrapper.setProperyValues,在這個過程中會查詢所有屬性的set方法並且處理property對應值,利用之前註冊到BeanWrapper中的PropertyEditor,如果是引用型別還需要向容器請求對應的bean,在處理時還會快取之前的處理結果到PropertyValue的resolvedDescriptor屬性。
bean初始化
到這裡bean的屬性填充工作已經完成了,接下來呼叫initializeBean方法來完成一些初始化工作:
- 啟用Aware介面
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
- 呼叫所有已註冊的BPP的postProcessBeforeInitialization
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
- 如果實現了InitializingBean介面,呼叫afterPropertiesSet方法,如果定義了init-mothod,呼叫對應的方法
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
- 呼叫所有已註冊BPP的postProcessAfterInitialization方法
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;
}
註冊析構回撥
bean析構回撥主要有一下幾種方式:
- DestructionAwareBeanPostProcessor的postProcessBeforeDestruction方法,註冊這種特殊的BPP到容器
- DisposableBean的destroy方法,bean實現DisposableBean介面
- bean定義指定destroy-method
註冊一個實現了DisposableBean介面的DisposableBeanAdapter類到容器中,bean銷燬時會觸發該類的destroy方法,在destroy方法中一次觸發上面列出的析構回撥:
public void destroy() {
if (this.beanPostProcessors != null && !this.beanPostProcessors.isEmpty()) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((DisposableBean) bean).destroy();
return null;
}
}, acc);
}
else {
((DisposableBean) bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToCall = determineDestroyMethod();
if (methodToCall != null) {
invokeCustomDestroyMethod(methodToCall);
}
}
}
註冊bean
bean的例項化初始化工作已經完成之後把bean註冊到容器中:- 把bean名稱從singletonsCurrentlyInCreation雜湊表中刪除
- 把bean例項註冊到容器中,新增到singletonObjects雜湊表中
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);
}
}
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.containsKey(beanName) &&
!this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
返回bean
bean建立工作完成之後接下來的工作是把bean返回給應用層:
- 如果bean不是FactoryBean或者bean名稱是以&開頭,那麼直接返回bean例項給應用層
- 如果bean是FactoryBean,那麼呼叫FactoryBean.getObject,把返回的物件返回給應用層。
程式碼在AbstractBeanFactory的getObjectForBeanInstance方法:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
至此bean的初始化程式碼分析就全部完成了,程式碼太多,感覺文章寫得有點亂,抽空再整理整理