Spring核心容器之Bean創(chuàng)建過(guò)程詳解
前言
獲取 Bean 的方法是 getBean,其來(lái)自 BeanFactory 繼承的 AbstractAutowireCapableBeanFactory 抽象類(lèi)繼承的 AbstractBeanFactory 抽象類(lèi)中。
1、整體流程
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
...
// 通過(guò) beanName 獲取 Bean 實(shí)例
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
// 檢索所需的 bean 類(lèi)型
@Override
public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
// 使用顯式參數(shù)創(chuàng)建 Bean 實(shí)例時(shí)要使用的參數(shù)
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
...
}
getBean 有多個(gè)重載方法,可分為通過(guò) Bean 名稱(chēng)或通過(guò) Class 獲取 Bean 對(duì)象,這些重載方法底層都是調(diào)用 doGetBean 方法。
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
/**
* 1、如果獲取的 Bean 類(lèi)型是 FactoryBean,則參數(shù) name 會(huì)以“&”為前綴。這里會(huì)去掉該修飾符,并返回.
* 2、如果是手動(dòng)注冊(cè)的別名,則將其解析為規(guī)范的名稱(chēng)
*/
final String beanName = transformedBeanName(name);
Object bean;
/**
* 1、單例 Bean 在 Spring 的同一個(gè)容器內(nèi)只會(huì)被創(chuàng)建一次,后續(xù)再獲取 Bean,直接從單例緩存中獲取
* 2、這里先從單例 Bean 的緩存容器中,嘗試獲取目標(biāo) Bean
* ( getSingleton 方法中存在解決單例 Bean 循環(huán)依賴(lài)問(wèn)題的具體方案,這部分會(huì)在后面的章節(jié)詳細(xì)討論)
*/
Object sharedInstance = getSingleton(beanName);
// 如果存在目標(biāo) Bean
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
// 目標(biāo) Bean 是否正在被創(chuàng)建
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 + "'");
}
}
// 1、不論是單例還是原型的實(shí)例對(duì)象,最終都要通過(guò) getObjectForBeanInstance 進(jìn)行轉(zhuǎn)換,最終得到的才是符合要求的bean實(shí)例。
// 2、有時(shí)候存在如 FactoryBean 這種并不是直接返回實(shí)例本身,而是返回指定方法返回的實(shí)例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 如果不存在目標(biāo) Bean
else {
// 如果當(dāng)前正在創(chuàng)建原型 Bean,則處于循環(huán)依賴(lài)中,且原型 Bean 無(wú)法解決循環(huán)依賴(lài),所以拋出異常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果 beanDefinitionMap 也就是容器中不存在目標(biāo) Bean,則嘗試從父級(jí) beanFactory 中獲取
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 獲取真正 beanName。如果獲取的 Bean 類(lèi)型是 FactoryBean,則去掉 beanName 的修飾符“&”
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 遞歸到 BeanFactory 中尋找
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 將指定的 bean 標(biāo)記為已經(jīng)創(chuàng)建(或?qū)⒁獎(jiǎng)?chuàng)建),即將 beanName 加入 alreadyCreated 集合中
markBeanAsCreated(beanName);
}
try {
// 通過(guò) beanName 獲取對(duì)應(yīng)的 BeanDefinition,如果獲取 BeanDefinition 是子類(lèi) BeanDefinition,
// 則通過(guò)與父級(jí)合并,返回目標(biāo) bean 的 RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 檢查bean是否是抽象的,如果是則拋出異常
checkMergedBeanDefinition(mbd, beanName, args);
// 獲取目標(biāo) bean 所依賴(lài)的其它 bean 名稱(chēng)
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
// 若存在依賴(lài)則需要遞歸實(shí)例化依賴(lài)的 bean
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);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
/* 開(kāi)始創(chuàng)建目標(biāo) bean 實(shí)例,根據(jù) bean 的 scope 執(zhí)行不同的創(chuàng)建方式。單例,原型,其他的scope */
// 這是單例的 bean 創(chuàng)建方式
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 創(chuàng)建 Bean 的核心方法
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 = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// prototype 類(lèi)型的 bean 創(chuàng)建方式
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);
}
// 其它類(lèi)型
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;
}
}
// 將 Bean 的類(lèi)型轉(zhuǎn)換為 getBean 時(shí)指定的 requireType 類(lèi)型
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.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
整個(gè)方法的過(guò)程可以概括為:
- 解析 beanName
- 從單例 Bean 實(shí)例的緩存容器中,嘗試獲取目標(biāo) Bean ,若存在,則直接執(zhí)行最后一步,將 Bean 的類(lèi)型轉(zhuǎn)換為 getBean 時(shí)指定的 requireType 類(lèi)型,之后返回
- 若不存在,則進(jìn)入創(chuàng)建 Bean 實(shí)例的流程
- 如果當(dāng)前正在創(chuàng)建原型 Bean 實(shí)例,則處于循環(huán)依賴(lài)中,且原型 Bean 無(wú)法解決循環(huán)依賴(lài),所以拋出異常
- 如果當(dāng)前 BeanFactory 中不存在目標(biāo) BeanDefinition,則從父 BeanFactory 獲取
- 獲取目標(biāo) BeanDefinition,如果獲取的 BeanDefinition 是子類(lèi) BeanDefinition(如 GenericBeanDefinition),則通過(guò)與父級(jí)合并,返回目標(biāo) bean 的 RootBeanDefinition
- 如果存在依賴(lài)的 Bean,則先實(shí)例化這些依賴(lài)的 Bean
- 依據(jù)當(dāng)前 Bean 的作用域,開(kāi)始實(shí)例化 Bean ,單例或原型
- 判斷實(shí)例化的 Bean 是否是 FactoryBean 類(lèi)型
- 將 Bean 的類(lèi)型轉(zhuǎn)換為 getBean 時(shí)指定的 requireType 類(lèi)型
- 最后返回 Bean 實(shí)例
以上就是 getBean 方法的大致流程,其中有兩個(gè)頻繁出現(xiàn)且非常重要的方法,一個(gè)是處理 FactoryBean 的 getObjectForBeanInstance方法,另一個(gè)是創(chuàng)建 Bean 的核心實(shí)現(xiàn) createBean 方法。
2、核心流程
2.1 解析 FactoryBean
關(guān)于 FactoryBean 在上一篇《Spring(七)核心容器 - 鉤子接口》文章中已經(jīng)討論過(guò),F(xiàn)actoryBean 是 Spring 提供的鉤子接口,其屬于一種特殊的 Bean,不同于普通的 Bean,它是用來(lái)創(chuàng)建 Bean 實(shí)例的,屬于工廠 Bean,不過(guò)它和普通的創(chuàng)建不同,它提供了更為靈活的方式,一般用來(lái)創(chuàng)建那些創(chuàng)建過(guò)程比較復(fù)雜的 Bean。
而 FactoryBean 則是通過(guò) getObjectForBeanlnstance 進(jìn)行解析。getObjectForBeanlnstance 是個(gè)高頻率使用的方法,無(wú)論是從緩存中獲得 bean 還是根據(jù)不同的 scope 策略加載bean。總之,我們得到 bean 的實(shí)例后要做的第一步就是調(diào)用這個(gè)方法來(lái)檢測(cè)一下正確性,其實(shí)就是用于檢測(cè)當(dāng)前 bean 是否是 FactoryBean 類(lèi)型的 bean ,如果是,那么需要調(diào)用該 bean 對(duì)應(yīng)的 FactoryBean 實(shí)例中的 getObject() 方法返回值作為真正返回的對(duì)象。
所以,當(dāng)我們 getBean 的時(shí)候,有兩種可能,一種是返回普通的 Bean,另一種是返回通過(guò) getObjectForBeanInstance 方法解析 FactoryBean 返回的 Bean。
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 如果 beanName 以“&”為前綴,但對(duì)應(yīng)的 bean 不是 FactoryBean 類(lèi)型,則拋異常
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// 校驗(yàn)已獲取的 bean
// 1、如果該 bean 不是 FactoryBean 類(lèi)型,直接返回
// 2、如果是 FactoryBean 類(lèi)型,且 beanName 以“&”為前綴,說(shuō)明想獲取的是 FactoryBean ,也是直接返回
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// 從緩存中嘗試獲取 FactoryBean 創(chuàng)建的對(duì)象
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 到這里已確定 beanInstance 一定是 FactoryBean 類(lèi)型,所以進(jìn)行強(qiáng)轉(zhuǎn)
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// 獲取 bean 對(duì)應(yīng)的 BeanDefinition
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
// 當(dāng)前 bean 是否是用戶(hù)定義的,而不是應(yīng)用程序自己定義的
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 解析 FactoryBean 的核心方法
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
這個(gè)方法很簡(jiǎn)單,大多是些輔助代碼以及一些功能性的判斷,真正的核心代碼在 getObjectFromFactoryBean 方法中。
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 如果是單例 bean
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
// 嘗試從緩存中獲取,緩存中存儲(chǔ)的是已經(jīng)通過(guò) FactoryBean 創(chuàng)建的 bean
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 通過(guò) FactoryBean 創(chuàng)建真正的 bean
object = doGetObjectFromFactoryBean(factory, beanName);
// 這里大概是 在執(zhí)行上一步 doGetObjectFromFactoryBean 方法過(guò)程中,該 bean 已被其它線程創(chuàng)建并緩存了起來(lái)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else { // 如果沒(méi)有
if (shouldPostProcess) { // Bean 是否要進(jìn)行后置處理
...
try {
// 執(zhí)行后置處理器(關(guān)于后置處理器已在上篇文章討論過(guò))
object = postProcessObjectFromFactoryBean(object, beanName);
}
// catch ...
}
...
}
}
return object;
}
}
else { // 如果不是單例 bean
// 通過(guò) FactoryBean 創(chuàng)建真正的 bean
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
// 執(zhí)行后置處理器
object = postProcessObjectFromFactoryBean(object, beanName);
}
// catch ...
}
return object;
}
}
接著進(jìn)入該方法中更為核心的 doGetObjectFromFactoryBean 方法:
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
// try...catch...
else {
// 調(diào)用 FactoryBean 的 getObject 方法,返回真正的 bean
object = factory.getObject();
}
}
// try...catch...
...
return object;
}可以看到,最后調(diào)用的就是 FactoryBean.getObject 方法
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
}
當(dāng)某個(gè) bean 的實(shí)例化過(guò)程比較復(fù)雜時(shí),可通過(guò)實(shí)現(xiàn) FactoryBean 接口,然后在重寫(xiě)的 getObject 方法中定義實(shí)例化 bean 的邏輯,以后獲取該 bean 時(shí),會(huì)通過(guò)調(diào)用 getObject 方法進(jìn)行返回。值得注意的是 mybatis 底層就是通過(guò) FactoryBean 來(lái)實(shí)現(xiàn)。
2.2 從 createBean 開(kāi)始
接著進(jìn)入創(chuàng)建 Bean 的下一步 createBean 方法:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 根據(jù)設(shè)置的 class 屬性或 className 來(lái)解析得到 Class 引用
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 對(duì) override 屬性進(jìn)行標(biāo)記和驗(yàn)證,本質(zhì)上是處理 lookup-method 和 replaced-method 標(biāo)簽
try {
mbdToUse.prepareMethodOverrides();
}
// catch...
try {
// 執(zhí)行 BeanPostProcessors 后置處理器,如果有 bean 返回,則不執(zhí)行接下來(lái)創(chuàng)建 bean 的操作,直接返回該 bean
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// catch...
try {
// 創(chuàng)建 Bean 的核心方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
// catch...
}
繼續(xù)進(jìn)入 doCreateBean 方法中:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// BeanWrapper 包裝了 bean 對(duì)象,緩存了 bean 的內(nèi)省結(jié)果,并可以訪問(wèn) bean 的屬性、設(shè)置 bean 的屬性值
BeanWrapper instanceWrapper = null;
// 如果是單例,嘗試獲取對(duì)應(yīng)的 BeanWrapper
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
/*
* 說(shuō)明對(duì)應(yīng)的bean還沒(méi)有創(chuàng)建,用對(duì)應(yīng)的策略(工廠方法、構(gòu)造函數(shù))創(chuàng)建 bean 實(shí)例,以及簡(jiǎn)單初始化
*
* 將 beanDefinition 轉(zhuǎn)成 BeanWrapper,大致流程如下:
* 1. 如果存在工廠方法,則使用工廠方法初始化
* 2. 否則,如果存在多個(gè)構(gòu)造函數(shù),則根據(jù)參數(shù)確定構(gòu)造函數(shù),并利用構(gòu)造函數(shù)初始化
* 3. 否則,使用默認(rèn)構(gòu)造函數(shù)初始化
*/
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 從 BeanWrapper 中獲取包裝的 bean 實(shí)例
final Object bean = instanceWrapper.getWrappedInstance();
// 從 BeanWrapper 獲取包裝 bean 的 class 引用
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 執(zhí)行 MergedBeanDefinitionPostProcessor 后置處理器。
//(這里涉及一個(gè)極其重要的后置處理器實(shí)現(xiàn) AutowiredAnnotationBeanPostProcessor,其主要用來(lái)處理 @Autowired 注解,這部分會(huì)在后面詳細(xì)討論)
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
// catch...
mbd.postProcessed = true;
}
}
// 檢查是否需要提前曝光,避免循環(huán)依賴(lài)(循環(huán)依賴(lài)問(wèn)題會(huì)在后面詳細(xì)討論)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 開(kāi)始初始化 bean
Object exposedObject = bean;
try {
// 對(duì) bean 進(jìn)行填充,將各個(gè)屬性值注入,如果存在依賴(lài)的 bean 則進(jìn)行遞歸初始化
populateBean(beanName, mbd, instanceWrapper);
// 執(zhí)行一系列的初始化方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// catch...
// 再次檢查是否循環(huán)依賴(lài)
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
}
}
}
}
// 注冊(cè)DisposableBean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// catch...
return exposedObject;
}
該方法整體流程如下:
- 如果是單例,嘗試從緩存中獲取 bean 的包裝器 BeanWrapper,并清除緩存
- 如果不存在對(duì)應(yīng)的 Wrapper,則說(shuō)明 bean 未被實(shí)例化,創(chuàng)建 bean 實(shí)例
- 執(zhí)行 MergedBeanDefinitionPostProcessor 后置處理器
- 檢查是否需要提前曝光,避免循環(huán)依賴(lài)
- 屬性填充,將所有屬性填充至bean 的實(shí)例中。
- 執(zhí)行一系列的初始化方法(回調(diào)鉤子接口)
- 再次檢查是否存在循環(huán)依賴(lài)
- 注冊(cè) DisposableBean
該過(guò)程中有幾個(gè)需要重點(diǎn)介紹的方法,分別是創(chuàng)建 Bean 實(shí)例的 createBeaninstance 方法、注入 Bean 屬性的 populateBean 方法以及執(zhí)行 Bean 初始化方法的 initializeBean 方法。
2.2.1 創(chuàng)建 Bean 實(shí)例
從 createBeaninstance 開(kāi)始:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
Class<?> beanClass = resolveBeanClass(mbd, beanName);
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());
}
// 如果有用于創(chuàng)建 bean 實(shí)例的回調(diào)方法
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 如果工廠方法不為空,則使用工廠方法進(jìn)行實(shí)例化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 利用構(gòu)造函數(shù)進(jìn)行實(shí)例化,解析并確定目標(biāo)構(gòu)造函數(shù)
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 一個(gè)類(lèi)可能有多個(gè)構(gòu)造函數(shù),需要根據(jù)參數(shù)來(lái)確定具體的構(gòu)造函數(shù)
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 如果已經(jīng)解析過(guò),則使用已經(jīng)確定的構(gòu)造方法
if (resolved) {
if (autowireNecessary) {
// 依據(jù)構(gòu)造函數(shù)注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默認(rèn)構(gòu)造函數(shù)構(gòu)造
return instantiateBean(beanName, mbd);
}
}
// 根據(jù)參數(shù)確定構(gòu)造函數(shù)
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 使用默認(rèn)的構(gòu)造函數(shù)
return instantiateBean(beanName, mbd);
}
以上主要分為:
- 使用工廠方法進(jìn)行實(shí)例化
- 通過(guò)構(gòu)造函數(shù)實(shí)例化
不管是通過(guò)工廠方法還是構(gòu)造方法來(lái)實(shí)例化對(duì)象,到這里得到的也僅僅是一個(gè) bean 的最初實(shí)例,還不是我們最終期望的 bean,因?yàn)楹竺孢€需要對(duì) bean 實(shí)例進(jìn)行初始化處理,注入相應(yīng)的屬性值等。
2.2.2 初始化 Bean 實(shí)例 - 屬性注入
屬性注入通過(guò) populateBean 方法實(shí)現(xiàn):
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 判斷實(shí)例化的 bean 是否為空
if (bw == null) {
// 返回是否有為此 bean 定義的屬性值,如果有,則拋異常,提示 “無(wú)法將屬性值應(yīng)用于空實(shí)例”
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
// 沒(méi)有,則跳過(guò)屬性填充階段以獲取空實(shí)例
else {
// Skip property population phase for null instance.
return;
}
}
// 在設(shè)置屬性之前,先執(zhí)行 InstantiationAwareBeanPostProcessors 后置處理器,這些后置處理器可以用其它方式注入屬性,如字段注入。
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 當(dāng)使用了 InstantiationAwareBeanPostProcessors 后置處理器注入屬性,則結(jié)束屬性注入流程,直接返回
if (!continueWithPropertyPopulation) {
return;
}
// 獲取 bean 實(shí)例的屬性值集合
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根據(jù)名稱(chēng)自動(dòng)注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根據(jù)類(lèi)型自動(dòng)注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 返回此工廠是否擁有 InstantiationAwareBeanPostProcessor
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否進(jìn)行依賴(lài)檢查
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
// 在屬性注入前執(zhí)行 InstantiationAwareBeanPostProcessor 后置處理器
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
// 進(jìn)行依賴(lài)檢查
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
if (pvs != null) {
// 執(zhí)行屬性注入
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
2.2.3 初始化 Bean 實(shí)例 - 執(zhí)行初始化方法(回調(diào)鉤子接口)
接著進(jìn)入 initializeBean 方法,在該方法中會(huì)回調(diào)許多在 Bean 初始化階段執(zhí)行的方法。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// 回調(diào) Aware 系列接口
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 回調(diào) BeanPostProcessor 后置處理器的 postProcessBeforeInitialization 方法
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 回調(diào) InitializingBean 的 afterPropertiesSet 方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 回調(diào) BeanPostProcessor 后置處理器的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
可以看到,在 Bean 的初始化階段,分別回調(diào)了 Aware 系列接口、BeanPostProcessor 后置處理器、InitializingBean 。這三個(gè)接口都屬于 Spring 的鉤子接口,是 Spring 開(kāi)放出來(lái)的擴(kuò)展接口,可以影響 Bean 的生命周期。
Bean 的初始化階段
1、回調(diào) Aware 系列接口
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
// 如果當(dāng)前 Bean 繼承了 BeanNameAware 接口,則回調(diào)接口中的 setBeanName 方法,并傳遞 beanName 參數(shù)
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
// 這個(gè) BeanClassLoaderAware 接口傳遞的是 ClassLoader
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
// 這個(gè) BeanFactoryAware 接口傳遞的是 AbstractAutowireCapableBeanFactory
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
這里被回調(diào)的 Aware 接口有三個(gè),分別是 BeanNameAware 、BeanClassLoaderAware、BeanFactoryAware。
2、回調(diào) BeanPostProcessor 后置處理器的 postProcessBeforeInitialization 方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// getBeanPostProcessors 方法獲取所有的 BeanPostProcessor 后置處理器的實(shí)現(xiàn),并循環(huán)執(zhí)行 postProcessBeforeInitialization 方法,參數(shù)是當(dāng)前 Bean 以及 beanName 。
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
其中有一個(gè)后置處理器的實(shí)現(xiàn) ApplicationContextAwareProcessor ,其用來(lái)對(duì)剩余的 Aware 接口進(jìn)行回調(diào):
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
//...
invokeAwareInterfaces(bean);
//...
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
3、回調(diào) InitializingBean 的 afterPropertiesSet 方法
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//..
((InitializingBean) bean).afterPropertiesSet();
//..
}4、回調(diào) BeanPostProcessor 后置處理器的 postProcessAfterInitialization 方法
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// getBeanPostProcessors 方法獲取所有的 BeanPostProcessor 后置處理器的實(shí)現(xiàn),并循環(huán)執(zhí)行 postProcessAfterInitialization 方法,參數(shù)是當(dāng)前 Bean 以及 beanName 。
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}到這里,創(chuàng)建 Bean 的核心流程就討論結(jié)束,可歸納為:
- 解析 beanName
- 從單例 Bean 實(shí)例的緩存容器中,嘗試獲取目標(biāo) Bean
- 緩存不存在則開(kāi)始實(shí)例化 Bean ,區(qū)分單例或原型
- 實(shí)例化 Bean、初始化 Bean、執(zhí)行初始化方法及回調(diào)鉤子接口
- 判斷實(shí)例化的 Bean 是否是 FactoryBean 類(lèi)型
到此這篇關(guān)于Spring核心容器之Bean創(chuàng)建過(guò)程詳解的文章就介紹到這了,更多相關(guān)Spring的Bean創(chuàng)建過(guò)程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java利用AlphaComposite類(lèi)合并圖像
這篇文章主要介紹了Java利用AlphaComposite類(lèi)合并圖像,幫助大家更好的利用Java處理圖像,感興趣的朋友可以了解下2020-10-10
Java遞歸讀取文件例子_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
本文通過(guò)一段示例代碼給大家介紹了java遞歸讀取文件的方法,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-05-05
java實(shí)現(xiàn)微信公眾號(hào)掃一掃
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)微信公眾號(hào)掃一掃,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04
Java基本知識(shí)點(diǎn)之變量和數(shù)據(jù)類(lèi)型
這篇文章主要給大家介紹了關(guān)于Java基本知識(shí)點(diǎn)之變量和數(shù)據(jù)類(lèi)型的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04

