先聊聊IOC
IoC(Inversion of Control) 控制反轉(zhuǎn),是spring框架的精髓,簡單來說,就是創(chuàng)建過程你不管,交給容器。與之對應(yīng)的兩個重要的類:
- BeanFactory - 接口的定義,定義了最基礎(chǔ)的操作接口,具體功能依賴實現(xiàn)類
- ApplicationContext - 實現(xiàn)了BeanFactory,并擴(kuò)展其功能
spring中的IOC
Spring以往通過xml文件加載bean,過程大致如下:
- 通過 xml 文件加載,xml文件舉例:
<bean id="hello" class="cn.test.service.Hello">
<property name="content" value="hello"/>
</bean>
- 加載相關(guān)屬性
- 反射實例化對象
- xml中的autowire
注意:xml中也可以配置 autowire 會自動注入,參數(shù) byName,意思是通過name去尋找依賴,通過這個方式解決依賴的注入。
<!-- 通過設(shè)置 autowire 屬性,我們就不需要像上面那樣顯式配置依賴了 -->
<bean name="serviceAutowire" class="cn.test.autowire.Service" autowire="byName"/>
- 解決配置bean太多的問題 引入FactoryBean(注意不是BeanFactory)
- ApplicationContextAware引入
在我們的web程序中,用spring來管理各個實例(bean), 有時在程序中為了使用已被實例化的bean, 通常會用到這樣的代碼
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext-common.xml");
AbcService abcService = (AbcService)appContext.getBean("abcService");
這會重新裝載applicationContext-common.xml并實例化上下文bean,如果有些線程配置類也是在這個配置文件中,那么會造成做相同工作的的線程會被啟兩次。一次是web容器初始化時啟動,另一次是上述代碼顯示的實例化了一次。當(dāng)于重新初始化一遍,這樣就產(chǎn)生了冗余。
解決方法
不用類似new ClassPathXmlApplicationContext()的方式,從已有的spring上下文取得已實例化的bean。通過ApplicationContextAware接口進(jìn)行實現(xiàn)。
- BeanPostProcessor 是 bean 實例化時的后置處理器,包含兩個方法,其源碼如下:
public interface BeanPostProcessor {
// bean 初始化前的回調(diào)方法
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
// bean 初始化后的回調(diào)方法
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
BeanPostProcessor 是 Spring 框架的一個擴(kuò)展點,通過實現(xiàn) BeanPostProcessor 接口,我們就可插手 bean 實例化的過程。比如大家熟悉的 AOP 就是在 bean 實例后期間將切面邏輯織入 bean 實例中的,AOP 也正是通過 BeanPostProcessor 和 IOC 容器建立起了聯(lián)系。
簡單來說:Spring容器從xml配置、java注解、spring注解中讀取bean配置信息,形成bean定義注冊表,填充bean的相關(guān)屬性,應(yīng)用通過getBean方法可以獲取其中的bean并實例化使用。
在Spring中,ClassPathXmlApplicationContext 的構(gòu)造過程,實際就是 Spring IoC 的初始化過程,ClassPathXmlApplicationContext的繼承關(guān)系如下圖:

BeanFactory的getBean的實現(xiàn)細(xì)節(jié)
回到這個類最基礎(chǔ)的一個方法,我們看getBean的過程是如何實現(xiàn)的。
獲取bean
BeanFactory中只定義了接口,getBean(String)方法實現(xiàn)細(xì)節(jié)體現(xiàn)5個實現(xiàn)類中。

- SimpleJndiBeanFactory - spring beanFactory接口的基于jndi的簡單實現(xiàn)
- StaticListableBeanFactory - 簡化版的BeanFactory,由于未實現(xiàn)BeanDefinitionRegistry,所以并不支持BeanDefinition的注冊操作
- StubWebApplicationContext - WebApplicationContext的實現(xiàn)
- AbstractApplicationContext - ApplicationContext是應(yīng)用的配置中的核心接口,應(yīng)用運行過程中是只讀的,但是可以通過實現(xiàn)其中的接口來達(dá)到reload的目的,AbstractApplicationContext是ApplicationContext的抽象類。相比于簡單的BeanFactory,ApplicationContext能在類內(nèi)部檢查特定的bean的定義,這個類會自動注冊BeanFactoryPostProcessor和BeanPostProcessors和ApplicationListeners
- AbstractBeanFactory - BeanFactory實現(xiàn)的一個抽象基類,我們重點研究。
GetBean過程:AbstractBeanFactory中doGetBean
繼承關(guān)系如下

BeanFactory實現(xiàn)的一個抽象基類,同時實現(xiàn)了ConfigurableBeanFactory的SPI。這個方法的getBean的實現(xiàn)(實際邏輯在doGetBean中),如下。
/**
* 返回一個實例,實例可以是共享的,獨立的或者是一個特定的bean
* @param name: bean的名稱
* @param requiredType: bean的類型
* @param args :其他參數(shù)集合,***僅僅用于創(chuàng)建新對象的時候,而不是獲取一個已經(jīng)存在的對象*** @Nullable 表示可以為空,不能為空用@NotNull修飾
* @param typeCheckOnly:是否對象只是用來做類型檢查而不是實際要用
* @return bean的實例
* @throws BeansException 如果bean不能被創(chuàng)建拋出異常
*/
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 去掉間接引用,去別名,使得最后的beanName是一個最簡的名稱,舉例:
// 1 有的name名字用&開頭,表示取FactoryBean本身,需要調(diào)用該方法。
// 2 name是別名,也需要轉(zhuǎn)為對應(yīng)的beanName
// 其中調(diào)用了BeanFactoryUtils中的方法,這個是bean操作的工具類,也很值得一讀,加個todo
final String beanName = transformedBeanName(name);
Object bean;
// 檢查單例緩存,獲取人工注冊的單例從beanName-->getSingleton獲得object-->getObjectForBeanInstance獲取bean
// sharedInstance 是從一個 Map<String, Object> singletonObjects結(jié)構(gòu)中獲取的對象,這個對象cache了bean name和bean instance的映射
// 實際接口調(diào)用過程中,有一些獲取不到,向前置earlySingletonObjects獲取的處理細(xì)節(jié),這里可以看源碼
Object sharedInstance = getSingleton(beanName);
// 如果 sharedInstance = null,則說明緩存里沒有對應(yīng)的實例,表明這個實例還沒創(chuàng)建。
// BeanFactory 并不會在一開始就將所有的單例 bean 實例化好,而是在調(diào)用 getBean 獲取bean的時候?qū)嵗簿褪?lazy加載
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 + "'");
}
}
// 條件1:如果 sharedInstance 是普通的單例 bean,下面的方法會直接返回。
// 條件2:如果是FactoryBean,且&開頭,是FactoryBean的解引用,返回FactoryBean,這個也是特殊的bean
// 條件1,2不滿足,如果sharedInstance是FactoryBean,調(diào)用getObjectFromFactoryBean這個函數(shù)從中獲取Object
// getObjectFromFactoryBean方法中調(diào)用doGetObjectFromFactoryBean,其中又調(diào)用factory.getObject()方法,這個方法是一個抽象接口,所有的Factory的實現(xiàn)類實現(xiàn)這個接口去create instance
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 進(jìn)入這個分支,則表明 sharedInstance 可能為空,
// 此時 beanName 對應(yīng)的 bean未創(chuàng)建,或者在父類中創(chuàng)建
// 如果當(dāng)前的bean已經(jīng)創(chuàng)建過(非父類),會返回失敗,應(yīng)該是循環(huán)引用導(dǎo)致的。
// debug到代碼內(nèi)部,prototypesCurrentlyInCreation.set有個分支:else if (curVal instanceof String)不明白為什么要有這個分支,但是不影響后續(xù)閱讀,這里加個todo。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 檢查bean的定義是否已經(jīng)出現(xiàn)在工廠中
// 先檢查父親工廠中是否有
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 沒找到,就遞歸地向上尋找
// 遞歸過程中根據(jù)不同的參數(shù)分治
// getBean 方法有很多重載,工廠模式了解一下
// 比如 getBean(String name, Object... args),我們在首次獲取,某個 bean 時,可以傳入用于初始化 bean 的參數(shù)數(shù)組(args)
// BeanFactory 會根據(jù)這些參數(shù),去匹配合適的構(gòu)造方法構(gòu)造 bean 實例。
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
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);
}
}
// 用alreadyCreated保存需要創(chuàng)建的beanName,如果只是做typeCheck,可以不用創(chuàng)建bean
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 貫穿父子關(guān)系去獲取RootBeanDefinition
// RootBeanDefinition是BeanDefinition最常用地實現(xiàn)類,對應(yīng)配置文件中bean元素標(biāo)簽。在配置文件中可以定義父<bean>和子<bean>,父<bean>用RootBeanDefiniton表示,子<bean>用ChildBeanDefinition表示。
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 當(dāng)前版本spring-beans-5.1.10只是在檢查 !mbd.isAbstract()
checkMergedBeanDefinition(mbd, beanName, args);
// 初始化bean的依賴,舉例:初始化一個店鋪,店鋪內(nèi)有基本的設(shè)施,店鋪依賴設(shè)施,這里先檢查設(shè)施能否初始化。
// todo:這里有個好奇,setDependsOn什么時候被賦值的?
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 再次檢查是否包含循環(huán)依賴
// 這里是最樸素的循環(huán)依賴檢查邏輯,內(nèi)部是深度優(yōu)先遍歷,
// 找到A的依賴B的集合set<B>,然后判斷set<B>的每個元素的依賴集合中是否依賴A
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 給當(dāng)前bean注冊一個依賴bean,對應(yīng)下面的dep,銷毀順序是:依賴bean銷毀后,當(dāng)前bean才被銷毀
// 注冊后,下次判斷循環(huán)依賴有可以檢查到這次新注冊的這組依賴關(guān)系
registerDependentBean(dep, beanName);
try {
// 遞歸調(diào)用自己,來做檢查,好多冗余操作啊...
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 創(chuàng)建bean的實例,其中核心方法是createBean和getObjectForBeanInstance,這一大段只不過是區(qū)分單例,原型和其他的處理情況而已。
// todo: 有時間要再讀讀createBean和getObjectForBeanInstance的源碼。
// 單例情況
if (mbd.isSingleton()) {
// 從匿名函數(shù)返回中獲取單例對象
sharedInstance = getSingleton(beanName, () -> {
try {
// 創(chuàng)建一個bean
// todo:create是一個抽象接口,具體的實現(xiàn)邏輯在子類中,這里以后有時間可以讀一下源碼
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 從緩存中明確的移除單例:避免在創(chuàng)建流程中因為緩存導(dǎo)致的循環(huán)引用,同時移除任何關(guān)于這個bean的臨時引用。
// 刪除的位置包含singletonObjects,singletonFactories,earlySingletonObjects,registeredSingletons,disposableBeans,dependentBeanMap
destroySingleton(beanName);
throw ex;
}
});
// 從bean的實例中獲取對象
// bean的實例可能是一個普通bean,也可能是FactoryBean,如果是普通Bean可以直接返回,如果是FactoryBean,需要從中再獲取到bean的實例。這個方法前面也提到過
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 如果是原型(參考原型模式的概念)
else if (mbd.isPrototype()) {
// 如果是原型,創(chuàng)建一個新實例
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) {
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;
}
}
// 類型檢查:判斷需要的類型是否匹配實際的bean實例。
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// todo: 通過類型轉(zhuǎn)化來判斷是否類型匹配,這個方法的源碼也值得一讀。
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
// todo: ClassUtils也是一個值得讀源碼的工具類
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
主要流程已經(jīng)在代碼的注釋中寫清楚了,重點的幾個邏輯我再總結(jié)一下:
1 去掉間接引用,去別名,使得最后的beanName是一個最簡的名稱transformedBeanName(name)
2 檢查單例緩存,獲取人工注冊的單例中獲取對象,利用該對象生成bean,生成方法中區(qū)分對待一般的bean和FactoryBean
3 第2步驟如果為null,從父類中獲取bean和FactoryBean
4 父類中沒有的話合并 BeanDefinition
5 處理 depends-on 依賴
6 創(chuàng)建并緩存 bean
7 調(diào)用 getObjectForBeanInstance 方法,生成 bean 實例
8 類型檢查和轉(zhuǎn)化
CreateBean過程
看上述核心代碼,我們不難發(fā)現(xiàn),有一個核心函數(shù)getSingleton一直在被調(diào)用

這個方法中傳入了一個匿名函數(shù),匿名函數(shù)中調(diào)用createBean,這是我們創(chuàng)建bean 的一段核心邏輯。我們先來看下getSingleton的代碼邏輯
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
// 緩存中獲取bean,不為空則直接返回
Object singletonObject = this.singletonObjects.get(beanName);
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 + "'");
}
// beforeSingletonCreation 將bean添加到 singletonsCurrentlyInCreation 的集合中,集合中存放的是正在創(chuàng)建的bean
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
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;
}
// 創(chuàng)建完成,將bean從正在創(chuàng)建的集合中移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 將 <beanName, singletonObject> 映射緩存到 singletonObjects中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
總結(jié)一下上述過程:
- 1 從singletonObjects獲取能獲取則直接獲取,singletonObjects可以看作緩存
- 2 不能獲取進(jìn)入創(chuàng)建流程,先將 beanName 添加到 singletonsCurrentlyInCreation
- 3 getObject 調(diào)用 createBean 方法,創(chuàng)建bean
- 4 beanName 從 singletonsCurrentlyInCreation 中移除
- 5 <beanName, singletonObject> 添加至 singletonObjects
createBean是流程中創(chuàng)建bean的核心方法,我們繼續(xù)看下這個createBean方法的實現(xiàn)??梢运岩幌乱韵潞瘮?shù)
return createBean(beanName, mbd, args);
在AbstractBeanFactory中只定義了一個抽象接口
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException;
接口的實現(xiàn)在AbstractAutowireCapableBeanFactory中的createBean方法
createBean方法和getBean方法有一些類似,就是真正getBean前后都做了很多事情,getBean的核心邏輯封裝在另外一個方法中。
這里就不帖詳細(xì)的源碼了,整個代碼結(jié)構(gòu)就是如下形式:
- pre-createBean:
- 解析bean的類型
- prepareMethodOverrides,override method的處理,實際在處理lookup-method 和 replace-method 配置(bean配置中的兩個關(guān)鍵字)
- 初始化前應(yīng)用后置處理 resolveBeforeInstantiation,后置處理返回的 bean 不為空,則直接返回(這里也可能返回bean)
- 核心邏輯:Object beanInstance = doCreateBean(beanName, mbdToUse, args);
- post-createBean:日志記錄,返回對象
resolveBeforeInstantiation會生成bean,但是我們這里先不聊,因為和AOP原理相關(guān),這里先不擴(kuò)展,另外一個生成bean的核心邏輯寫在doCreateBean中。我們具體看這個方法的實現(xiàn)。
ps:spring框架中,真實的執(zhí)行邏輯一般都放在do開頭的方法中,doCreateBean也是一樣。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// bean初始化
// BeanWrapper 是bean 的包裝類,通過這個包裝,能方便的設(shè)置和獲取bean的實例屬性
BeanWrapper instanceWrapper = null;
// 單例先從factoryBeanInstanceCache移除,返回為null表示不存在,那么直接用createBeanInstance創(chuàng)建
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// createBeanInstance創(chuàng)建createBean,使用三種策略之一:
// factory method, constructor autowiring 或者 simple instantiation
// factory method, 工廠方法
// constructor autowiring,構(gòu)造方式自動注入
// simple instantiation,通過無參數(shù)構(gòu)造方法
// 另外bean的信息配置了lookup-method和replace-method會另外處理。
// 返回類型是BeanWrapper,能用于填充對象的屬性,todo:BeanWrapper的源碼也值得讀一讀。
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 原始的bean,還沒有填充屬性
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 允許后置處理器post-processors 修改 MBD
synchronized (mbd.postProcessingLock) {
// postProcessed默認(rèn)為false
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 緩存單例用于解決循環(huán)依賴,earlySingletonExposure用于表示是否提前暴露,即使生命周期處理接口帶來的循環(huán)依賴也包含
// earlySingletonExposure的滿足的條件:
// 條件: bean 是否是單例類型 & 允許循環(huán)依賴 & bean 是處于創(chuàng)建的狀態(tài)中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 匿名函數(shù)獲取早期bean引用,如果bean中的方法被AOP切點匹配到,會進(jìn)入aop相關(guān)邏輯
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 初始化bean的實例
Object exposedObject = bean;
try {
// 給bean裝載屬性,也是一個核心方法,todo:值得一讀的源碼
populateBean(beanName, mbd, instanceWrapper);
// 剩余的初始化工作
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// 注冊bean,為當(dāng)前bean的銷毀提供策略和實現(xiàn)
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
以上創(chuàng)建過程給各小結(jié):
- 緩存中獲取BeanWrapper,獲取不到就創(chuàng)建BeanWrapper
- 一些預(yù)處理,MergedBeanDefinitionPostProcessor; 暴露 bean 的早期引用(early reference),用于處理循環(huán)依賴問題
- populateBean填充屬性
- initializeBean進(jìn)行剩下的初始化
- 注冊銷毀邏輯
createBeanInstance
doCreateBean這個方法中,有個很重要的核心方法createBeanInstance。
復(fù)述一下前面的批注:
createBeanInstance創(chuàng)建createBean,使用三種策略之一:
- factory method, constructor autowiring 或者 simple instantiation
- factory method, 工廠方法
- constructor autowiring,構(gòu)造方式自動注入
- simple instantiation,通過無參數(shù)構(gòu)造方法,另外bean的信息配置了lookup-method和replace-method會另外處理。返回類型是BeanWrapper,能用于填充對象的屬性
instanceWrapper = createBeanInstance(beanName, mbd, args);
下面重點剖析這段代碼
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 檢測訪問權(quán)限,默認(rèn)情況下,對于public的類有訪問權(quán)限,沒有訪問權(quán)限拋出異常
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 工廠方法不為空,通過工廠方法構(gòu)建bean對象
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
// 如果是處理同一個bean,第一次處理的時候,做個標(biāo)記,之后同類型的bean做相同處理即可
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 默認(rèn)方法構(gòu)造bean對象
return instantiateBean(beanName, mbd);
}
}
// 通過后處理器返回一系列構(gòu)造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 條件mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR:bean的autowire屬性是否為constructor
// 條件mbd.hasConstructorArgumentValues(): bean中是否配置了<construct-arg/>
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
autowireConstructor
上面的代碼通過不同的條件選擇調(diào)用autowireConstructor,
這個方法比較復(fù)雜,到了這一步已經(jīng)大致知道創(chuàng)建過程是如何的了,
這一層后續(xù)繼續(xù)詳解吧。
springboot中BeanWrapper的生成方法autowireConstructor