Spring源碼分析 Bean創建和獲取
Spring獲取Bean源碼
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected Object doGetBean(String name, Class requiredType, final Object args[], boolean typeCheckOnly)
throws BeansException
{
final String beanName;
Object bean;
final RootBeanDefinition mbd;
Object prototypeInstance;
beanName = transformedBeanName(name);
// 先嚐試從緩存中獲取bean,對於那些單例模式的Bean,緩存獲取
Object sharedInstance = getSingleton(beanName);
if(sharedInstance != null && args == null)
{
if(logger.isDebugEnabled())
if(isSingletonCurrentlyInCreation(beanName))
logger.debug((new StringBuilder()).append("Returning eagerly cached instance of singleton bean '").append(beanName).append("' that is not fully initialized yet - a consequence of a circular reference").toString());
else
logger.debug((new StringBuilder()).append("Returning cached instance of singleton bean '").append(beanName).append("'").toString());
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
break MISSING_BLOCK_LABEL_544;
}
if(isPrototypeCurrentlyInCreation(beanName))
throw new BeanCurrentlyInCreationException(beanName);
BeanFactory parentBeanFactory = getParentBeanFactory();
if(parentBeanFactory != null && !containsBeanDefinition(beanName))
{
String nameToLookup = originalBeanName(name);
if(args != null)
return parentBeanFactory.getBean(nameToLookup, args);
else
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
if(!typeCheckOnly)
markBeanAsCreated(beanName);
mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
String dependsOn[] = mbd.getDependsOn();
if(dependsOn != null)
{
String arr$[] = dependsOn;
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; i$++)
{
String dependsOnBean = arr$[i$];
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
}
if(mbd.isSingleton())
{
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject()
throws BeansException
{
try
{
return createBean(beanName, mbd, args);
}
catch(BeansException ex)
{
destroySingleton(beanName);
throw ex;
}
}
final String val$beanName;
final RootBeanDefinition val$mbd;
final Object val$args[];
final AbstractBeanFactory this$0;
{
this$0 = AbstractBeanFactory.this;
beanName = s;
mbd = rootbeandefinition;
args = aobj;
super();
}
}
);
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
break MISSING_BLOCK_LABEL_544;
}
if(!mbd.isPrototype())
break MISSING_BLOCK_LABEL_399;
prototypeInstance = null;
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
afterPrototypeCreation(beanName);
break MISSING_BLOCK_LABEL_383;
Exception exception;
exception;
afterPrototypeCreation(beanName);
throw exception;
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
break MISSING_BLOCK_LABEL_544;
String scopeName = mbd.getScope();
Scope scope = (Scope)scopes.get(scopeName);
if(scope == null)
throw new IllegalStateException((new StringBuilder()).append("No Scope registered for scope '").append(scopeName).append("'").toString());
try
{
Object scopedInstance = scope.get(beanName, new ObjectFactory() {
public Object getObject()
throws BeansException
{
beforePrototypeCreation(beanName);
Object obj = createBean(beanName, mbd, args);
afterPrototypeCreation(beanName);
return obj;
Exception exception1;
exception1;
afterPrototypeCreation(beanName);
throw exception1;
}
final String val$beanName;
final RootBeanDefinition val$mbd;
final Object val$args[];
final AbstractBeanFactory this$0;
{
this$0 = AbstractBeanFactory.this;
beanName = s;
mbd = rootbeandefinition;
args = aobj;
super();
}
}
);
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch(IllegalStateException ex)
{
throw new BeanCreationException(beanName, (new StringBuilder()).append("Scope '").append(scopeName).append("' is not active for the current thread; ").append("consider defining a scoped proxy for this bean if you intend to refer to it from a singleton").toString(), ex);
}
if(requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass()))
{
try
{
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch(TypeMismatchException ex)
{
if(logger.isDebugEnabled())
logger.debug((new StringBuilder()).append("Failed to convert bean '").append(name).append("' to required type [").append(ClassUtils.getQualifiedName(requiredType)).append("]").toString(), ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
} else
{
return bean;
}
}
如圖所示,源碼分析
首先獲取bean的名稱 beanName = transformedBeanName(name);
然後查看緩存中bean是否存在,如下圖
Object sharedInstance = getSingleton(beanName);
private final Map singletonObjects = new ConcurrentHashMap(64);
private final Map alreadyCreated;
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
/*1*/
Object singletonObject = singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName))
synchronized (singletonObjects) {
singletonObject = earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory singletonFactory = (ObjectFactory) singletonFactories
.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
earlySingletonObjects.put(beanName, singletonObject);
singletonFactories.remove(beanName);
}
}
}
return singletonObject == NULL_OBJECT ? null : singletonObject;
}
/*2*/
protected void markBeanAsCreated(String beanName) {
alreadyCreated.put(beanName, Boolean.TRUE);
}
/*3*/
String dependsOn[] = mbd.getDependsOn();
if(dependsOn != null)
{
String arr$[] = dependsOn;
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; i$++)
{
String dependsOnBean = arr$[i$];
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
}
緊接着,如圖1 通過singletonObjects緩存對象去獲取對象,由於可見,Spring底層用的緩存大多數是緩存在Map結構中,緩存對象首次初始化的時候爲空,構建之前會先調用 如圖2-markBeanAsCreated()標明此處bean狀態爲構建中, 繼續分析如下
如圖3 後續會查看當前bean是否有依賴引用,如A依賴B,首先會把B創建成功後,然後注入到A中
下敘真實獲取bean對象源碼
public static transient Object instantiateClass(Constructor ctor,
Object args[]) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
ReflectionUtils.makeAccessible(ctor);
return ctor.newInstance(args);
} catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Is it an abstract class?", ex);
} catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Is the constructor accessible?", ex);
} catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Illegal arguments for constructor", ex);
} catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Constructor threw exception", ex.getTargetException());
}
}
public static void makeAccessible(Constructor ctor) {
if ((!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor
.getDeclaringClass().getModifiers())) && !ctor.isAccessible())
ctor.setAccessible(true);
}
由此得出結論,bean創建實例是通過java反射來實現,創建之前會檢查訪問修飾類型,如果不是public可見的,調用setAccessible(true);得到私有構造方法來構建對象實例,接下來要把bean中默認設置的屬性值注入,創建出來的單例bean對象添加到緩存中,供下次直接使用,到此bean創建和獲取流程結束
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (singletonObjects) {
//Map緩存單例bean對象
singletonObjects.put(beanName,
singletonObject == null ? NULL_OBJECT : singletonObject);
singletonFactories.remove(beanName);
earlySingletonObjects.remove(beanName);
registeredSingletons.add(beanName);
}
}
總結:
SpringBean創建和獲取
- Spring的bean實際上是緩存在CurrentHashMap對象中
- 創建bean之前,首先要將該bean的創建標識設定好,表示該bean已經即將被創建,其目的增強緩存效率
- 根據bean的Scope屬性來確定是singleton還是prototype等範圍,然後創建相應bean對象
- 通過java反射創建bean的實例
- 接下來,尋找bean的屬性值,完成屬性注入
- 將所創建出來的singleton對象添加到緩存中,供下次調用使用
作者簡介:張程 技術研究
更多文章請關注微信公衆號:zachary分解獅 (frankly0423)