1.概述
首先Bean就是一些JAVA對象,只不過這些Bean不是我們主動new
出來的,而是交個(gè)Spring IOC容器創(chuàng)建并管理的,因此Bean的生命周期受Spring IOC容器控制,Bean生命周期大致分為以下幾個(gè)階段:
-
Bean的實(shí)例化(Instantiation):Spring框架會取出BeanDefinition的信息進(jìn)行判斷當(dāng)前Bean的范圍是否是singleton的,是否不是延遲加載的,是否不是FactoryBean等,最終將一個(gè)普通的singleton的Bean通過反射進(jìn)行實(shí)例化
-
Bean的屬性賦值(Populate):Bean實(shí)例化之后還僅僅是個(gè)"半成品",還需要對Bean實(shí)例的屬性進(jìn)行填充,Bean的屬性賦值就是指 Spring 容器根據(jù)BeanDefinition中屬性配置的屬性值注入到 Bean 對象中的過程。
-
Bean的初始化(Initialization):對Bean實(shí)例的屬性進(jìn)行填充完之后還需要執(zhí)行一些Aware接口方法、執(zhí)行BeanPostProcessor方法、執(zhí)行InitializingBean接口的初始化方法、執(zhí)行自定義初始化init方法等。該階段是Spring最具技術(shù)含量和復(fù)雜度的階段,并且Spring高頻面試題Bean的循環(huán)引用問題也是在這個(gè)階段體現(xiàn)的;
-
Bean的使用階段:經(jīng)過初始化階段,Bean就成為了一個(gè)完整的Spring Bean,被存儲到單例池singletonObjects中去了,即完成了Spring Bean的整個(gè)生命周期,接下來Bean就可以被隨心所欲地使用了。
-
Bean的銷毀(Destruction):Bean 的銷毀是指 Spring 容器在關(guān)閉時(shí),執(zhí)行一些清理操作的過程。在 Spring 容器中, Bean 的銷毀方式有兩種:銷毀方法destroy-method和 DisposableBean 接口。
2.Bean生命周期詳解和使用案例
BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor,BeanPostProcessor
這三個(gè)后置處理器的調(diào)用時(shí)機(jī)都在Spring Bean生命周期中是不嚴(yán)謹(jǐn)?shù)模凑丈厦嫖覀儗ean生命周期的階段劃分,只有BeanPostProcessor
作用于Bean的生命周期中,而BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor
是針對BeanDefinition的,所以不屬于Bean的生命周期中。
BeanPostProcessor
在Bean生命周期的體現(xiàn)如下圖所示:
Bean的生命周期和人的一生一樣都會經(jīng)歷從出生到死亡,中間是一個(gè)漫長且復(fù)雜的過程,接下來我們就來整體分析一下Bean生命周期的核心流程和相關(guān)接口回調(diào)方法的調(diào)用時(shí)機(jī),同時(shí)這里想強(qiáng)調(diào)一下Bean的生命周期也是面試的高頻考點(diǎn),對核心流程務(wù)必要掌握清楚,這里用一張流程圖進(jìn)行詳述展示,是重點(diǎn)、重點(diǎn)、重點(diǎn)。
根據(jù)上面的Bean生命周期核心流程做如下代碼演示示例:
Bean定義:
@Data
@AllArgsConstructor
public class Boo implements InitializingBean, DisposableBean, BeanNameAware {
private Long id;
private String name;
public Boo() {
System.out.println("boo實(shí)例化構(gòu)造方法執(zhí)行了...");
}
@PostConstruct
public void initMethod() {
System.out.println("boo執(zhí)行初始化init()方法了...");
}
@PreDestroy
public void destroyMethod() {
System.out.println("boo執(zhí)行初始化destroy()方法了...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("boo執(zhí)行InitializingBean的afterPropertiesSet()方法了...");
}
@Override
public void destroy() throws Exception {
System.out.println("boo執(zhí)行DisposableBean的destroy()方法了...");
}
@Override
public void setBeanName(String name) {
System.out.println("boo執(zhí)行BeanNameAware的setBeanName()方法了...");
}
}
實(shí)現(xiàn)InstantiationAwareBeanPostProcessor:
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> BeanClass, String BeanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor的before()執(zhí)行了...." + BeanName);
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object Bean, String BeanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor的after()執(zhí)行了...." + BeanName);
return false;
}
}
實(shí)現(xiàn)BeanPostProcessor:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object Bean, String BeanName) throws BeansException {
System.out.println("BeanPostProcessor的before()執(zhí)行了...." + BeanName);
return Bean;
}
@Override
public Object postProcessAfterInitialization(Object Bean, String BeanName) throws BeansException {
System.out.println("BeanPostProcessor的after()執(zhí)行了...."+ BeanName);
return Bean;
}
}
執(zhí)行下面的配置類測試方法:
@ComponentScan(basePackages = {"com.shepherd.common.config"})
@Configuration
public class MyConfig {
@Bean
public Boo boo() {
return new Boo();
}
public static void mAIn(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
String[] BeanDefinitionNames = applicationContext.getBeanDefinitionNames();
// 遍歷Spring容器中的BeanName
for (String BeanDefinitionName : BeanDefinitionNames) {
System.out.println(BeanDefinitionName);
}
// 這里調(diào)用的applicationContext的close()觸發(fā)Bean的銷毀回調(diào)方法
applicationContext.close();
}
}
名為boo的Bean相關(guān)運(yùn)行結(jié)果如下:
InstantiationAwareBeanPostProcessor的before()執(zhí)行了....boo
boo實(shí)例化構(gòu)造方法執(zhí)行了...
InstantiationAwareBeanPostProcessor的after()執(zhí)行了....boo
boo執(zhí)行BeanNameAware的setBeanName()方法了...
BeanPostProcessor的before()執(zhí)行了....boo
boo執(zhí)行初始化init()方法了...
boo執(zhí)行InitializingBean的afterPropertiesSet()方法了...
BeanPostProcessor的after()執(zhí)行了....boo
......
boo執(zhí)行初始化destroy()方法了...
boo執(zhí)行DisposableBean的destroy()方法了...
根據(jù)控制臺打印結(jié)果可以boo的相關(guān)方法執(zhí)行順序嚴(yán)格遵從上面流程圖,同時(shí)當(dāng)我們執(zhí)行容器applicationContext
的關(guān)閉方法close()
會觸發(fā)調(diào)用bean的銷毀回調(diào)方法。
3.淺析Bean生命周期源碼實(shí)現(xiàn)
DefaultListableBeanFactory
是Spring IOC的Bean工廠的一個(gè)默認(rèn)實(shí)現(xiàn),IOC大部分核心邏輯實(shí)現(xiàn)都在這里,可關(guān)注。Bean生命周期就是創(chuàng)建Bean的過程,這里我們就不在拐彎抹角兜圈子,直接來到DefaultListableBeanFactory
繼承的AbstractAutowireCapableBeanFactory
的#doCreateBean()
方法,之前說過在Spring框架中以do開頭的方法都是核心邏輯實(shí)現(xiàn)所在
protected Object doCreateBean(String BeanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the Bean.
// BeanWrapper 是對 Bean 的包裝,其接口中所定義的功能很簡單包括設(shè)置獲取被包裝的對象,獲取被包裝 Bean 的屬性描述器
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// <1> 單例模型,則從未完成的 FactoryBean 緩存中刪除
instanceWrapper = this.factoryBeanInstanceCache.remove(BeanName);
}
if (instanceWrapper == null) {
// <2> 使用合適的實(shí)例化策略來創(chuàng)建新的實(shí)例:工廠方法、構(gòu)造函數(shù)自動注入、簡單初始化
instanceWrapper = createBeanInstance(BeanName, mbd, args);
}
// 包裝的實(shí)例對象
Object Bean = instanceWrapper.getWrappedInstance();
// 包裝的實(shí)例class類型
Class<?> BeanType = instanceWrapper.getWrappedClass();
if (BeanType != NullBean.class) {
mbd.resolvedTargetType = BeanType;
}
// Allow post-processors to modify the merged Bean definition.
// <3> 判斷是否有后置處理
// 如果有后置處理,則允許后置處理修改 BeanDefinition
synchronized (mbd.postProcessingLock) {
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;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// <4> 解決單例模式的循環(huán)依賴
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");
}
// 提前將創(chuàng)建的 Bean 實(shí)例加入到 singletonFactories 中
// 這里是為了后期避免循環(huán)依賴
addSingletonFactory(BeanName, () -> getEarlyBeanReference(BeanName, mbd, Bean));
}
// Initialize the Bean instance.
// 開始初始化 Bean 實(shí)例對象
Object exposedObject = Bean;
try {
// <5> 對 Bean 進(jìn)行填充,將各個(gè)屬性值注入,其中,可能存在依賴于其他 Bean 的屬性
// 則會遞歸初始依賴 Bean
populateBean(BeanName, mbd, instanceWrapper);
// <6> 調(diào)用初始化方法
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);
}
}
// <7> 循環(huán)依賴處理
if (earlySingletonExposure) {
// 獲取 earlySingletonReference
Object earlySingletonReference = getSingleton(BeanName, false);
// 只有在存在循環(huán)依賴的情況下,earlySingletonReference 才不會為空
if (earlySingletonReference != null) {
// 如果 exposedObject 沒有在初始化方法中被改變,也就是沒有被增強(qiáng)
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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register Bean as disposable.
try {
// <8> 注冊 Bean的銷毀邏輯
registerDisposableBeanIfNecessary(BeanName, Bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), BeanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
由上面代碼可知,Bean的創(chuàng)建過程核心步驟如下:
-
createBeanInstance(BeanName, mbd, args) 進(jìn)行Bean的實(shí)例化 -
populateBean(BeanName, mbd, instanceWrapper)進(jìn)行Bean的屬性填充賦值 -
initializeBean(BeanName, exposedObject, mbd)處理Bean初始化之后的各種回調(diào)事件 -
registerDisposableBeanIfNecessary(BeanName, Bean, mbd)注冊Bean的銷毀接口 -
解決創(chuàng)建Bean過程中的循環(huán)依賴,Spring使用三級緩存解決循環(huán)依賴,這也是一個(gè)重要的知識點(diǎn),這里不詳細(xì)闡述,后面會安排
接下來我們就來看看和Bean初始化階段相關(guān)各種回調(diào)事件執(zhí)行方法#initializeBean()
,分析一下上面流程圖的執(zhí)行順序是怎么實(shí)現(xiàn)的。
protected Object initializeBean(final String BeanName, final Object Bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(BeanName, Bean);
return null;
}
}, getAccessControlContext());
}
else {
// 涉及到的回調(diào)接口點(diǎn)進(jìn)去一目了然,代碼都是自解釋的
// BeanNameAware、BeanClassLoaderAware或BeanFactoryAware
invokeAwareMethods(BeanName, Bean);
}
Object wrappedBean = Bean;
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessBeforeInitialization 回調(diào)
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, BeanName);
}
try {
// init-methods
// 或者是實(shí)現(xiàn)了InitializingBean接口,會調(diào)用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()) {
// BeanPostProcessor 的 postProcessAfterInitialization 回調(diào)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, BeanName);
}
return wrappedBean;
}
至于Bean的銷毀流程與Bean初始化類似,從上面的使用示例中看可以得出當(dāng)容器關(guān)閉時(shí),才會對Bean銷毀方法進(jìn)行調(diào)用。銷毀過程是這樣的。順著close()-> doClose() -> destroyBeans() -> destroySingletons() -> destroySingleton() -> destroyBean() -> Bean.destroy()
,會看到最終調(diào)用Bean的銷毀方法。這里就不在展示源碼細(xì)節(jié)啦,有興趣的話自行去調(diào)試查看了解
4.總結(jié)
以上全部就是對Spring Bean生命周期的全面總結(jié), Spring 的 Bean 容器機(jī)制是非常強(qiáng)大的,它可以幫助我們輕松地管理 Bean 對象,并且提供了豐富的生命周期回調(diào)方法,允許我們在 Bean 的生命周期中執(zhí)行自己的特定操作,這對于我們平時(shí)工作使用中進(jìn)行增強(qiáng)擴(kuò)展至關(guān)重要,因此掌握Bean的生命周期是必須的。