當我們通過向Spring容器獲取某個bean的時候,總是調用Spring中重載的各種getBean方法。那麼,getBean中的流程是什麼樣的?
通過本文,你將對getBean方法的主流程有一個詳細的認識。
入口當然是getBean方法:
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args,
boolean typeCheckOnly) throws BeansException {
//beanName轉換,這裏主要有兩方面的考慮:
//1:如果beanName是以&開頭的,則表明是要返回FactoryBean本身
//而不是其生產出來的對象,而FactoryBean存儲的時候,跟普通的bean一樣
//2:如果傳入的是別名,則是需要轉換爲實際的beanName的
final String beanName = transformedBeanName(name);
Object bean;
// 檢查bean是否已經存在了緩存中
Object sharedInstance = getSingleton(beanName);
//不爲空則表明之前被創建過
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
.............
}
//這裏對於普通的bean,則會直接的返回,
//如果是FactoryBean類型的則會創建對應的實例返回
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//如果是正在創建的Prototype類型的bean,無法處理該類型循環依賴的問題,則直接拋出異常信息
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 查看父類中是否有相關的bean的定義信息
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 如果name是以&開頭的 則返回&+beanName的格式
String nameToLookup = originalBeanName(name);
if (args != null) {
//遞歸去父類中查找
return (T) parentBeanFactory.getBean(nameToLookup, args);
}else {
//遞歸去父類中查找
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
//將父類的定義的BeanDefinition與子類的BeanDefinition進行合併覆蓋
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
//判斷bean是否有dependsOn 類的依賴
//如果沒有循環依賴,則先創建所dependsOn依賴的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
//這裏主要是判斷是否有以下這種類型的依賴:
//<bean id="beanA" class="BeanA" depends-on="beanB">
//<bean id="beanB" class="BeanB" depends-on="beanA">
//如果有,則直接拋出異常
if (isDependent(beanName, dep)) {
.......
}
registerDependentBean(dep, beanName);
getBean(dep);
}
}
// 處理完bean的依賴關係,則開始來創建bean
if (mbd.isSingleton()) {
//創建單例的bean,這裏的createBean下文將詳細講解
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}}});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
//創建原型的bean
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance,
name, beanName, mbd);
}
else {
//創建其他生命週期的bean
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
.........
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
........
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// bean的類型轉換
if (requiredType != null &&
bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
........
}
}
return (T) bean;
}
整個getBean大的流程如上所示,在以上源碼中,我們將看下以下的幾個的方法:
1:transformedBeanName方法:
protected String transformedBeanName(String name) {
//如果beanName是以&開頭的 則截取掉開頭的&
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
public String canonicalName(String name) {
String canonicalName = name;
// 循環的去獲取別名,直到獲取到真實的beanName
//aliasA->aliasB->beanName
String resolvedName;
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
2:getSingleton方法
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
//判斷是否有緩存起來的bean
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//singletonObjects保存的爲實例化並賦值過的bean,可以直接使用
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//earlySingletonObjects主要是保存允許提前暴露出來的bean
//主要是爲了解決循環依賴的問題
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);
}
3:getObjectForBeanInstance方法
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
//如果name是以&開頭的 但是不是FactoryBean,則直接拋出異常
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// 則beanInstance可能是一個普通的bean,也可能是一個FactoryBean
// 如果是一個普通的bean,則直接返回
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//FactoryBean創建出bean實例返回
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
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;
}
以上對getBean主流程以及其主要的幾個方法做了分析,下面將對其getBean的主流程做一個分析:
通過流程圖,將其主要的流程的輪廓給描述的出來。更加的直觀。在下文中,我將對Spring中createBean做一個詳細的描述