1. 引言“請你描述下 Spring Bean 的生命周期?”,這是面試官考察 Spring 的常用問題,可見是 Spring 中很重要的知識點。 我之前在準(zhǔn)備面試時,去網(wǎng)上搜過答案,大多以下圖給出的流程作為答案。
但是當(dāng)我第一次看到該圖時,就產(chǎn)生了很多困擾,“Aware,BeanPostProcessor......這些都是什么??!而且這么多步驟,太多了,該怎么記?。 ?。 其實要記憶該過程,還是需要我們先去理解,本文將從以下兩方面去幫助理解 Bean 的生命周期:
2. 生命周期的概要流程Bean 的生命周期概括起來就是?4 個階段:
下面我們結(jié)合代碼來直觀的看下,在 doCreateBean() 方法中能看到依次執(zhí)行了這 4 個階段: //?AbstractAutowireCapableBeanFactory.javaprotected
?Object?doCreateBean(final
?String
?beanName
,?
final
?RootBeanDefinition
?mbd
,?
final
?@Nullable
?
Object
[]
?args
)
????throws
?BeanCreationException?
{????
//?1.?實例化
????BeanWrapper
?instanceWrapper?
=?
null;????
if
?(
instanceWrapper?
==?
null)
?
{
????????instanceWrapper?
=
?createBeanInstance
(
beanName
,
?mbd
,
?args
);
????
}
????
Object
?exposedObject?
=
?bean
;????
try
?{????????
//?2.?屬性賦值
????????populateBean
(
beanName
,
?mbd
,
?instanceWrapper
);????????
//?3.?初始化
????????exposedObject?
=
?initializeBean
(
beanName
,
?exposedObject
,
?mbd
);
????
}????
//?4.?銷毀-注冊回調(diào)接口
????try
?{
????????registerDisposableBeanIfNecessary
(
beanName
,
?bean
,
?mbd
);
????
}????
return
?exposedObject
;
}由于初始化包含了第 3~7步,較復(fù)雜,所以我們進(jìn)到 initializeBean() 方法里具體看下其過程(注釋的序號對應(yīng)圖中序號): //?AbstractAutowireCapableBeanFactory.javaprotected?Object?initializeBean(final?String?beanName,?final?Object?bean,?@Nullable?RootBeanDefinition?mbd)?{????//?3.?檢查?Aware?相關(guān)接口并設(shè)置相關(guān)依賴????if?(System.getSecurityManager()?!=?null)?{????????AccessController.doPrivileged((PrivilegedAction<Object>)?()?->?{????????????invokeAwareMethods(beanName,?bean);????????????return?null;????????},?getAccessControlContext());????}????else?{????????invokeAwareMethods(beanName,?bean);????}????//?4.?BeanPostProcessor?前置處理????Object?wrappedBean?=?bean;????if?(mbd?==?null?||?!mbd.isSynthetic())?{????????wrappedBean?=?applyBeanPostProcessorsBeforeInitialization(wrappedBean,?beanName);????}????//?5.?若實現(xiàn)?InitializingBean?接口,調(diào)用?afterPropertiesSet()?方法????//?6.?若配置自定義的?init-method方法,則執(zhí)行????try?{????????invokeInitMethods(beanName,?wrappedBean,?mbd);????}????catch?(Throwable?ex)?{????????throw?new?BeanCreationException(????????????(mbd?!=?null???mbd.getResourceDescription()?:?null),????????????beanName,?"Invocation?of?init?method?failed",?ex);????}????//?7.?BeanPostProceesor?后置處理????if?(mbd?==?null?||?!mbd.isSynthetic())?{????????wrappedBean?=?applyBeanPostProcessorsAfterInitialization(wrappedBean,?beanName);????}????return?wrappedBean;}在 invokInitMethods() 方法中會檢查 InitializingBean 接口和 init-method 方法,銷毀的過程也與其類似: //?DisposableBeanAdapter.javapublic?void?destroy()?{????//?9.?若實現(xiàn)?DisposableBean?接口,則執(zhí)行?destory()方法????if?(this.invokeDisposableBean)?{????????try?{????????????if?(System.getSecurityManager()?!=?null)?{????????????????AccessController.doPrivileged((PrivilegedExceptionAction<Object>)?()?->?{????????????????????((DisposableBean)?this.bean).destroy();????????????????????return?null;????????????????},?this.acc);????????????}????????????else?{????????????????((DisposableBean)?this.bean).destroy();????????????}????????}????}????//?10.?若配置自定義的?detory-method?方法,則執(zhí)行????if?(this.destroyMethod?!=?null)?{????????invokeCustomDestroyMethod(this.destroyMethod);????}????else?if?(this.destroyMethodName?!=?null)?{????????Method?methodToInvoke?=?determineDestroyMethod(this.destroyMethodName);????????if?(methodToInvoke?!=?null)?{????????????invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));????????}????}}從 Spring 的源碼我們可以直觀的看到其執(zhí)行過程,而我們記憶其過程便可以從這 4 個階段出發(fā),實例化、屬性賦值、初始化、銷毀。其中細(xì)節(jié)較多的便是初始化,涉及了 Aware、BeanPostProcessor、InitializingBean、init-method 的概念。這些都是 Spring 提供的擴(kuò)展點,其具體作用將在下一節(jié)講述。 3. 擴(kuò)展點的作用3.1 Aware 接口若 Spring 檢測到 bean 實現(xiàn)了 Aware 接口,則會為其注入相應(yīng)的依賴。所以通過讓bean 實現(xiàn) Aware 接口,則能在 bean 中獲得相應(yīng)的 Spring 容器資源。 Spring 中提供的 Aware 接口有:
其代碼實現(xiàn)如下: //?AbstractAutowireCapableBeanFactory.javaprivate?void?invokeAwareMethods(final?String?beanName,?final?Object?bean)?{????if?(bean?instanceof?Aware)?{????????if?(bean?instanceof?BeanNameAware)?{????????????((BeanNameAware)?bean).setBeanName(beanName);????????}????????if?(bean?instanceof?BeanClassLoaderAware)?{????????????((BeanClassLoaderAware)?bean).setBeanClassLoader(bcl);????????}????????if?(bean?instanceof?BeanFactoryAware)?{????????????((BeanFactoryAware)?bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);????????}????}}以上是針對 BeanFactory 類型的容器,而對于 ApplicationContext 類型的容器,也提供了 Aware 接口,只不過這些 Aware 接口的注入實現(xiàn),是通過 BeanPostProcessor 的方式注入的,但其作用仍是注入依賴。
其代碼實現(xiàn)如下: //?ApplicationContextAwareProcessor.javaprivate?void?invokeAwareInterfaces(Object?bean)?{????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.2 BeanPostProcessorBeanPostProcessor 是 Spring 為*修改 bean *提供的強(qiáng)大擴(kuò)展點,其可作用于容器中所有 bean,其定義如下: public?interface?BeanPostProcessor?{????//?初始化前置處理????default?Object?postProcessBeforeInitialization(Object?bean,?String?beanName)?throws?BeansException?{????????return?bean;????}????//?初始化后置處理????default?Object?postProcessAfterInitialization(Object?bean,?String?beanName)?throws?BeansException?{????????return?bean;????}}常用場景有:
//?AbstractAutoProxyCreator.javapublic?Object?postProcessBeforeInstantiation(Class<?>?beanClass,?String?beanName)?{????TargetSource?targetSource?=?getCustomTargetSource(beanClass,?beanName);????if?(targetSource?!=?null)?{????????if?(StringUtils.hasLength(beanName))?{????????????this.targetSourcedBeans.add(beanName);????????}????????Object[]?specificInterceptors?=?getAdvicesAndAdvisorsForBean(beanClass,?beanName,?targetSource);????????Object?proxy?=?createProxy(beanClass,?beanName,?specificInterceptors,?targetSource);????????this.proxyTypes.put(cacheKey,?proxy.getClass());????????//?返回代理類????????return?proxy;????}????return?null;}3.3 InitializingBean 和 init-methodInitializingBean 和 init-method 是 Spring 為?bean 初始化提供的擴(kuò)展點。 InitializingBean接口 的定義如下: public?interface?InitializingBean?{????void?afterPropertiesSet()?throws?Exception;}在 afterPropertiesSet() 方法寫初始化邏輯。 指定 init-method 方法,指定初始化方法: <?xml?version="1.0"?encoding="UTF-8"?><beans?xmlns="http://www./schema/beans"???????xmlns:xsi="http://www./2001/XMLSchema-instance"???????xsi:schemaLocation="http://www./schema/beans?http://www./schema/beans/spring-beans.xsd">????<bean?id="demo"?class="com.chaycao.Demo"?init-method="init()"/></beans> DisposableBean 和 destory-method 與上述類似,就不描述了。 4. 總結(jié)最后總結(jié)下如何記憶 Spring Bean 的生命周期:
|
|
|