在Spring原始碼系列:BeanFactory的建立文章中我們談到了BeanFactory這容器,這個裡面提供了注入的實現介面。其具體的實現還需要從AbstractBeanFactory和DefaultListableBeanFactory中來看。今天就先擼一下AbstractBeanFactory這個類中的getBean這個方法。
1、getBean方法
getBean提供了四個過載方法,如下:
//通過name獲取Bean
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
//通過name和型別獲取Bean
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
//通過name和物件引數獲取Bean
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
//通過name、型別和引數獲取Bean
public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
return doGetBean(name, requiredType, args, false);
}
複製程式碼
從這四個過載方法的方法體中可以看出,他們都是通過doGetBean來實現的。所以doGetBean其實才是真正獲取Bean的地方,也是觸發依賴注入發生的地方。(這個方法比較長,分段來說)
2、doGetBean
先來看下方法的定義:
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
複製程式碼
- name 要檢索的bean的名稱
- requiredType 要檢索的bean所需的型別
- args 使用顯式引數建立bean例項時使用的引數(僅在建立新例項時應用,而不是在檢索現有例項時應用)
- typeCheckOnly 是否為型別檢查而獲得例項,而不是實際使用
//返回bean名稱,剝離工廠引用字首,並將別名解析為規範名稱。
final String beanName = transformedBeanName(name);
//宣告當前需要返回的bean物件
Object bean;
// 先從快取中獲取bean,處理已經被建立的單例模式的bean,
//對於此類bean的請求不需要重複的建立(singleton)
Object sharedInstance = getSingleton(beanName);
複製程式碼
如果當前獲取到的sharedInstance不為null並且引數為空,則進行FactoryBean的相關處理,並獲取FactoryBean的處理結果。
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
//返回指定的singleton bean是否正在建立(在整個工廠內)。
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的相關處理,並用來獲取FactoryBean的處理結果
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
複製程式碼
如果當前獲取到的sharedInstance為null,我們再來看下做了哪些處理(下面的都在一個大的else裡面):
else {
//分解到下面
}
複製程式碼
//在當前執行緒中,返回指定的prototype bean是否正在建立。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
複製程式碼
下面這段的作用是對Ioc容器中的BeanDefinition是否存在進行檢測,先是檢測當前BeanFactory中是否能夠獲取到,如果取不到則繼續到雙親容器中進行嘗試獲取,如果雙親還是取不到,則繼續向上一級父容器中嘗試獲取。
// 檢查該工廠是否存在bean定義。
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 如果沒有,則繼續檢查父類
String nameToLookup = originalBeanName(name);
if (args != null) {
// 用明確的引數代表父項。
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// 如果沒有args - >委託給標準的getBean方法。
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
複製程式碼
將指定的bean標記為已經建立(或即將建立);這裡允許bean工廠優化其快取以重複建立指定的bean。
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
複製程式碼
先根據beanName來獲取BeanDefinition,然後獲取當前bean的所有依賴bean,這裡是通過遞迴呼叫getBean來完成,直到沒有任何依賴的bean為止。
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//檢查給定的合併bean定義,可能丟擲驗證異常。
checkMergedBeanDefinition(mbd, beanName, args);
// 保證當前bean依賴的bean的初始化。
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
//遞迴處理依賴bean
getBean(dep);
}
}
複製程式碼
下面這段就是建立一個bean例項;這裡通過呼叫getSingleton方法來建立一個單例bean例項;從程式碼中可以看到,getSingleton的呼叫是通過getObject這個回撥函式來間接呼叫createBean完成的。
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
//回撥函式getObject
@Override
public Object getObject() throws BeansException {
try {
//建立bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
//發生異常則銷燬
destroySingleton(beanName);
throw ex;
}
}
});
//獲取給定bean例項的物件,無論是bean例項本身,還是FactoryBean建立的物件。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
複製程式碼
下面是建立prototype bean
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
//建立prototype bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
複製程式碼
最後是對建立的bean進行型別檢查,沒有問題就返回已經建立好的bean;此時這個bean是包含依賴關係的bean
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());
}
}
//返回bean
return (T) bean;
複製程式碼
getBean是依賴注入的起點,從上面的分析可以看出,bean的建立都是通過createBean來完成具體的建立的。createBean的具體實現是在AbstractAutowireCapableBeanFactory中的,這裡createBean不僅僅負責建立bean,還需要完成對bean的初始化。