在Spring源碼系列:BeanFactory的建立文章中咱們談到了BeanFactory這容器,這個裏面提供了注入的實現接口。其具體的實現還須要從AbstractBeanFactory和DefaultListableBeanFactory中來看。今天就先擼一下AbstractBeanFactory這個類中的getBean這個方法。java
一、getBean方法緩存
getBean提供了四個重載方法,以下:bash
//經過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的地方,也是觸發依賴注入發生的地方。(這個方法比較長,分段來講)ide
二、doGetBean函數
先來看下方法的定義:post
@SuppressWarnings("unchecked")
protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
複製代碼
//返回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裏面):ui
else {
//分解到下面
}
複製代碼
//在當前線程中,返回指定的prototype bean是否正在建立。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
複製代碼
下面這段的做用是對Ioc容器中的BeanDefinition是否存在進行檢測,先是檢測當前BeanFactory中是否可以獲取到,若是取不到則繼續到雙親容器中進行嘗試獲取,若是雙親仍是取不到,則繼續向上一級父容器中嘗試獲取。spa
// 檢查該工廠是否存在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。prototype
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的初始化。