Spring Bean生命周期
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”
優(yōu)質(zhì)文章,第一時間送達(dá)
作者 | 歪頭兒在帝都
來源 | urlify.cn/um6rIv
前言
Spring Bean生命周期是常見的面試題,也是日常開發(fā)中經(jīng)常用到的技術(shù)點(diǎn),在應(yīng)用開發(fā)中,常常需要執(zhí)行一些特殊的初始化工作,如建立數(shù)據(jù)庫連接,打開網(wǎng)絡(luò)連接,又比如在一些業(yè)務(wù)bean里,你想拿到Spring IOC容器,又或者是想拿到一些已經(jīng)實(shí)例化的Bean。同時,在服務(wù)結(jié)束時,也有一些銷毀銷毀工作需要執(zhí)行。為了便于工作的設(shè)計(jì),Spring IOC提供相關(guān)接口,可以讓應(yīng)用定制Bean的初始化和銷毀。
Spring Bean生命周期
先來看一下Spring Bean生命周期流程圖,方便對照后續(xù)的源碼分析。
Spring Bean生命周期從大的節(jié)點(diǎn)上分為4個過程:實(shí)例化、屬性賦值、初始化、銷毀。日常業(yè)務(wù)開發(fā)過程中,我們應(yīng)該涉及最多的兩個點(diǎn)就是初始化和銷毀,比如自定義Bean實(shí)現(xiàn)InitializingBean、DisposeableBean。
源碼分析
Spring IOC容器初始化
初始化從AbstractAutowireCapableBeanFactory.doCreateBean方法開始說起,我在對應(yīng)的代碼位置標(biāo)注了關(guān)鍵點(diǎn)
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
//1. Bean實(shí)例化
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
}
mbd.postProcessed = true;
}
}
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
//2.屬性賦值
this.populateBean(beanName, mbd, instanceWrapper);
//3.初始化
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
if (earlySingletonExposure) {
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;
int var13 = dependentBeans.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
if (!this.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.");
}
}
}
}
try {
//4.銷毀 - 注冊回調(diào)接口
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
為了保持代碼片段精簡,我刪掉了其中的logger代碼。
從以上代碼片段里可以看到我們上面總結(jié)的Spring生命后期4個關(guān)鍵點(diǎn)都有體現(xiàn),我們著重分析初始化和銷毀流程。
AbstractAutowireCapableBeanFactory.initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
//1.檢查Aware相關(guān)接口并設(shè)置相關(guān)依賴
//BeanNameAware, BeanClassLoaderAware, BeanFactoryAware
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
this.invokeAwareMethods(beanName, bean);
}
//2.BeanPostProcessor前置處理
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//BeanPostProcessor接口的postProcessBeforeInitialization回調(diào)
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
//3.若實(shí)現(xiàn)InitializingBean接口,則調(diào)用afterPropertiesSet()
//4.若配置自定義的init-method(), 則執(zhí)行。
try {
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
//5.BeanPostProcessor后置處理
if (mbd == null || !mbd.isSynthetic()) {
//BeanPostProcessor接口的postProcessAfterInitialization回調(diào)
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
AbstractAutowireCapableBeanFactory.invokeAwareMethods
invokeAwareMethod就是調(diào)用一系列Aware結(jié)尾的接口,比如
BeanNameAware、ApplicationContextAware、BeanFactoryAware。
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware)bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = this.getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware)bean).setBeanFactory(this);
}
}
}AbstractAutowireCapableBeanFactory.invokeInitMethods
invokeinitMethods就是調(diào)用InitializingBean接口的afterPropertiesSet,并且檢查自定義init-method。
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
boolean isInitializingBean = bean instanceof InitializingBean;
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(() -> {
((InitializingBean)bean).afterPropertiesSet();
return null;
}, this.getAccessControlContext());
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
((InitializingBean)bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
this.invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
從以上代碼片段可以看出Spring IOC容器創(chuàng)建Bean的過程, 涉及的過程包括實(shí)例化,銷毀,還包括BeanPostProcessor接口相關(guān)方法實(shí)現(xiàn),以上代碼片段我們分析了Spring容器初始化過程加載Bean的各種實(shí)現(xiàn),下面我們看下Spring容器銷毀階段。
容器銷毀
Spring容器銷毀過程調(diào)用鏈
Spring在這里用了適配器模式,也就是說最終的銷毀任務(wù)由DisposableBeanAdapter來完成,我們看下DisposeableBeanAdapter的結(jié)構(gòu)。
從結(jié)構(gòu)中可以看到bean屬性類型為Object, 也就是要銷毀的Bean,還有beanName屬性。
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
Iterator var1 = this.beanPostProcessors.iterator();
while(var1.hasNext()) {
DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)var1.next();
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
((DisposableBean)this.bean).destroy();
return null;
}, this.acc);
} else {
((DisposableBean)this.bean).destroy();
}
} catch (Throwable var3) {
}
}
if (this.destroyMethod != null) {
this.invokeCustomDestroyMethod(this.destroyMethod);
} else if (this.destroyMethodName != null) {
Method methodToInvoke = this.determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
this.invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
總結(jié)
Spring Bean生命周期分為4個階段和多個擴(kuò)展點(diǎn),擴(kuò)展點(diǎn)又分為影響多個Bean和單個Bean。
4個階段:實(shí)例化、屬性賦值、初始化、銷毀。
擴(kuò)展點(diǎn)
影響多個Bean
BeanPostProcessor
InstantiationAwareBeanPostProcessor
影響單個Bean
BeanNameAware
BeanFactoryAware
BeanClassLoaderAware
ApplicationContextAware
Spring生命周期中兩個關(guān)鍵的接口:InitializingBean, DisposableBean。
粉絲福利:Java從入門到入土學(xué)習(xí)路線圖
??????

??長按上方微信二維碼 2 秒
感謝點(diǎn)贊支持下哈 
