先看下簡(jiǎn)單的Spring應(yīng)用
public static void main(String[] args) {
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
TestBean bean = (TestBean)bf.getBean("test");
bean.test();
}
獲取bean的時(shí)候調(diào)用getBean方法,跟蹤源碼發(fā)現(xiàn)最后調(diào)用的是doGetBean方法
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
下面我們?cè)敿?xì)來看下doGetBean方法
獲取Bean對(duì)象整體流程
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
/*進(jìn)行beanName轉(zhuǎn)換,有兩個(gè)原因
*1)bean配置的時(shí)候可以配置別名懦傍,name可能是別名怨绣,需要轉(zhuǎn)換成對(duì)應(yīng)的真實(shí)beanName
*2)name可能是以&字符開頭的背亥,表明調(diào)用者想要獲取FactoryBean本身览闰,而非FactoryBean實(shí)現(xiàn)類所創(chuàng)建的bean
*/
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
/*
*
* 檢查緩存中或者實(shí)例工廠中是否有實(shí)例對(duì)象
*
* 因子在創(chuàng)建單例bean的時(shí)候回存在依賴注入的情況吨娜,而在創(chuàng)建依賴的時(shí)候?yàn)榱吮苊庋h(huán)依賴
* Spring創(chuàng)建bean的原則是不等bean創(chuàng)建完成就會(huì)將創(chuàng)建bean的ObjectFactory提早曝光
* 也就是將ObjectFactory加入到緩存中麻顶,一旦下個(gè)bean創(chuàng)建時(shí)需要依賴上個(gè)bean則直接使用ObjectFactory
*/
//直接嘗試從緩存中獲取或者singletonFactories中的ObjectFactory中獲取
Object sharedInstance = getSingleton(beanName);
/*
*如果sharedInstance為空赦抖,則說明緩存中沒有對(duì)應(yīng)的實(shí)例,表明這個(gè)類還沒創(chuàng)建
* BeanFactory并不會(huì)在一開始就將所有的單例bean實(shí)例化好辅肾,而且在調(diào)用getBean獲取
* bean時(shí)再實(shí)例化队萤,也即是懶加載
*
* getBean有很多重載方法,在首次獲取某個(gè)bean時(shí)宛瞄,可以傳入用于初始化bean的參數(shù)數(shù)組(args)浮禾,BeanFactory會(huì)根據(jù)這些
* 參數(shù)去匹配何時(shí)的構(gòu)造方法構(gòu)造bean實(shí)例。當(dāng)然份汗,如果單例bean早已創(chuàng)建好盈电,這里的args就沒用了
*
*/
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
/*
*如果sharedInstance是普通的單例bean,下面的方法會(huì)直接返回
* 但是如果sharedInstance是FactoryBean類型杯活,則需要調(diào)用getObject工廠方法獲取
* 真正的bean實(shí)例匆帚。如果用戶想要獲取FactoryBean本身,這里也不會(huì)特別的處理旁钧,直接返回即可
*/
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
/*
* 如果上面的條件不滿足吸重,則表明sharedInstance可能為空,此時(shí)beanName對(duì)應(yīng)的bean實(shí)例
* 可能還沒創(chuàng)建
* 還有一種可能歪今,如果當(dāng)前容器有父容器嚎幸,beanName對(duì)應(yīng)的bean實(shí)例可能在父容器中被創(chuàng)建
* 所以在創(chuàng)建實(shí)例前,需要先去父容器里檢查一下
*/
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//BeanFactory不緩存Prototype類型的bean寄猩,無法處理該類型的循環(huán)依賴問題
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//如果sharedInstance為空嫉晶,則到父容器中查詢bean的實(shí)例
BeanFactory parentBeanFactory = getParentBeanFactory();
//如果beanDefinitionMap中也就是在所有已經(jīng)加載過的類中不包括beanName則嘗試從parentFactory中查找
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
//獲取name對(duì)應(yīng)的beanName,如果name是以&字符開頭田篇,則返回&+beanName
String nameToLookup = originalBeanName(name);
//父容器是AbstractBeanFactory類型替废,調(diào)用父容器的doGetBean方法查找
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
//根據(jù)args是否為空,已決定調(diào)用父容器哪個(gè)方法獲取bean
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
//如果不是僅僅做類型檢查則是創(chuàng)建bean泊柬,這里要進(jìn)行記錄
if (!typeCheckOnly) {
markBeanAsCreated(beanName);//標(biāo)記當(dāng)前beanName對(duì)應(yīng)的bean已創(chuàng)建
}
try {
//合并父BeanDefinition和子BeanDefinition
//將存在XML配置文件的GenericBeanDefinition轉(zhuǎn)成RootBeanDefinition椎镣,如果指定BeanName是子bean的話同時(shí)合并父類的相關(guān)屬性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
//獲取bean所有的dependsOn,如果有依賴兽赁,則先加載依賴的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
/*
檢測(cè)是否存在循環(huán)依賴
*/
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//注冊(cè)依賴記錄
registerDependentBean(dep, beanName);
try {
//先加載依賴的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
/*
*這里并沒有直接調(diào)用 createBean 方法創(chuàng)建bean實(shí)例状答,而且通過getSingleton(String,ObjectFactory)方法獲取bean實(shí)例
* getSingleton(String,ObjectFactory)方法會(huì)在內(nèi)部調(diào)用ObjectFactory的getObject()方法創(chuàng)建bean
* 并在創(chuàng)建完成后冷守,將bean放入緩存中
*/
sharedInstance = getSingleton(beanName, () -> {
try {
//創(chuàng)建bean實(shí)例
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
//如果bean是FactoryBean類型,則調(diào)用工廠方法獲取真正的bean實(shí)例剪况,否則直接返回bean實(shí)例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);ge'?
}
//創(chuàng)建Prototype類型的bean實(shí)例
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
//創(chuàng)建其他類型的bean實(shí)例
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
//進(jìn)行類型轉(zhuǎn)換
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
beanName轉(zhuǎn)換
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
//處理掉beanName中的&字符
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
/*
* 該方法用于轉(zhuǎn)換別名
*/
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
/**
* 這里采用循環(huán)處理的原因是教沾,存在別名指向別名的可能
* <bean id="hello" class="com.df.Hello" />
* <alias name="hello" alias="aliasA" />
* <alias name="aliasA" alias="aliasB" />
* alisaB --> aliasA --> hello
*/
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
在Spring容器中,是按照BeanName和Bean對(duì)象一樣對(duì)應(yīng)進(jìn)行存儲(chǔ)的译断,通過beanName可以直接找到對(duì)應(yīng)的bean對(duì)象授翻。在配置時(shí),支持別名的方式進(jìn)行配置孙咪。通過別名獲取bean時(shí)堪唐,先找到別名對(duì)應(yīng)的真實(shí)BeanName,然后再通過beanName進(jìn)行查找
從緩存中獲取單例bean
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//嘗試從緩存中獲取單例bean實(shí)例
Object singletonObject = this.singletonObjects.get(beanName);
/*
* singletonObject為空翎蹈,說明還沒創(chuàng)建淮菠,或者還沒有完全創(chuàng)建好
* isSingletonCurrentlyInCreation是判斷beanName對(duì)應(yīng)的bean是否正在創(chuàng)建中
* 解決bean之間的循環(huán)依賴
*/
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//earlySingletonObjects中獲取提前曝光的bean 用于處理循環(huán)引用
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果如果 singletonObject = null,且允許提前曝光 bean 實(shí)例荤堪,則從相應(yīng)的 ObjectFactory 獲取一個(gè)原始的(raw)bean(尚未填充屬性)
if (singletonObject == null && allowEarlyReference) {
//獲取相應(yīng)的工廠類
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//提前曝光bean實(shí)例 合陵,用于解決循環(huán)依賴
singletonObject = singletonFactory.getObject();
//放入緩存中 這樣如果其他的bean依賴當(dāng)前bean,則可以從earlySingletonObjects中獲取
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
在Spring中澄阳,有很多緩存
singletonObjects:用于存放單例bean對(duì)象
earlySingletonObjects:也是用于存放單例bean對(duì)象拥知,它用于解決循環(huán)依賴
singletonFactories:存放創(chuàng)建bean對(duì)象的factoryObject
對(duì)于單類對(duì)象,由于每次獲取的都是同一個(gè)對(duì)象碎赢,為了提供效率低剔,Spring會(huì)將這些對(duì)象緩存起來。Spring容器中絕大多數(shù)對(duì)象都是單類的肮塞,所以每次調(diào)用getBean方法時(shí)襟齿,首先嘗試從緩存中獲取對(duì)應(yīng)的bean對(duì)象,提高了性能枕赵。
對(duì)于循環(huán)依賴的問題猜欺,后面專門會(huì)說
從實(shí)例中獲取bean對(duì)象
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//如果name以&開頭,但beanInatance卻不是FactoryBean拷窜,則認(rèn)為有問題
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
}
/*
上面判斷通過后替梨,表明beanInstance可能是一個(gè)普通的bean,也可能是一個(gè)FactoryBean
如果是一個(gè)普通的bean装黑,這里直接返回beanInstance即可
如果name是以&開頭的,則說明用戶最終想要獲取的是Factory本身弓熏,也直接返回
如果是FactoryBean恋谭,則要調(diào)用工廠方法生成一個(gè)實(shí)例
*/
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
/*
如果mbd為空,則從緩存中加載bean挽鞠。FactoryBean生成的單例bean會(huì)被緩存
在factoryBeanObjectCache集合中疚颊,不用每次都創(chuàng)建
*/
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
//到了這里狈孔,可以保證是FactoryBean類型了
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
//如果mbd為空。則判斷是否存在名字為beanName的beanDefine
if (mbd == null && containsBeanDefinition(beanName)) {
//合并BeanDefinition
mbd = getMergedLocalBeanDefinition(beanName);
}
//跟Aop相關(guān)材义,如果被Aop增強(qiáng)了均抽,則為true
//是否是用戶定義的而不是應(yīng)用程序本事定義的
boolean synthetic = (mbd != null && mbd.isSynthetic());
//調(diào)用getObjectFromFactoryBean
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
beanInstance只是初始狀態(tài)的bean,不一定是最終我們想要的bean其掂。如果是FactoryBean類型油挥,beanInstance只是FactoryBean的初始狀態(tài),我們正在需要的bean需要調(diào)用FactoryBean的factory-method方法來獲取
處理加載依賴
在bean配置中,可以通過depends-on屬性來配置加載依賴類款熬。此時(shí)Srping會(huì)優(yōu)先加載依賴的類深寥,然后再加載當(dāng)前bean
<bean id="sysinit" class="SystemInit">
<bean id="manager" class="CacheManager" depends-on="sysinit"/>
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
/*
檢測(cè)是否存在循環(huán)依賴,兩個(gè)bean
*/
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//注冊(cè)依賴記錄
registerDependentBean(dep, beanName);
try {
//先加載依賴的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
代碼邏輯很簡(jiǎn)單,從當(dāng)前bean的定義中獲取依賴類贤牛,然后注冊(cè)依賴記錄惋鹅,加載依賴類
根據(jù)不同的scope獲取bean對(duì)象
獲取單類bean
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//全局變量需要同步
synchronized (this.singletonObjects) {
//首先檢測(cè)beanName對(duì)應(yīng)的bean是否已經(jīng)加載過,因?yàn)閟ingleton模式其實(shí)就是復(fù)用以創(chuàng)建的bean殉簸,所以這一步是必須的
Object singletonObject = this.singletonObjects.get(beanName);
//只有沒加載過闰集,才能進(jìn)行初始化
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//創(chuàng)建前的操作 將此beanName加入singletonsCurrentlyInCreation緩存中, 標(biāo)記此bean正在創(chuàng)建中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//初始化bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//從singletonsCurrentlyInCreation中刪除
afterSingletonCreation(beanName);
}
if (newSingleton) {
//加入到緩存 并刪除創(chuàng)建過程中的輔助狀態(tài)
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
1)首先鎖住singletonObjects防止并發(fā)操作
2)再次確認(rèn)對(duì)應(yīng)的bean對(duì)象沒有創(chuàng)建
3)在創(chuàng)建前標(biāo)記beanName對(duì)應(yīng)的bean正在創(chuàng)建中般卑,上面從緩存中獲取單例的時(shí)候武鲁,可能會(huì)判斷
4)然后調(diào)用singletonFactory的getObejct方法創(chuàng)建bean對(duì)象
5)創(chuàng)建完成之后,從singletonsCurrentlyInCreation中刪除beanName
6)如果當(dāng)前bean是第一次創(chuàng)建對(duì)象椭微,則將bean對(duì)象加入到單例緩存中
Prototype類型bean的獲取
Prototype類型的bean每次獲取都會(huì)創(chuàng)建一個(gè)新的bean對(duì)象洞坑,代碼很簡(jiǎn)單,就是在對(duì)象創(chuàng)建前標(biāo)記正在創(chuàng)建蝇率,創(chuàng)建后刪除此標(biāo)記
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
其他scope類型bean的獲取
和Prototype類型bean獲取的區(qū)別在于會(huì)從scope中獲取
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
類型轉(zhuǎn)換
當(dāng)參數(shù)requiredType不為空迟杂,且bean對(duì)象不是requiredType類型實(shí)例時(shí),就會(huì)進(jìn)行類型緩存本慕,requiredType在調(diào)用getBean方法時(shí)傳入排拷,例如:
applicationContext.getBean("test",TestBean.class);
//進(jìn)行類型轉(zhuǎn)換
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}