小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

如何記憶 Spring Bean 的生命周期

 印度阿三17 2021-03-17

1. 引言

“請你描述下 Spring Bean 的生命周期?”,這是面試官考察 Spring 的常用問題,可見是 Spring 中很重要的知識點。

我之前在準(zhǔn)備面試時,去網(wǎng)上搜過答案,大多以下圖給出的流程作為答案。

如何記憶 Spring Bean 的生命周期


但是當(dāng)我第一次看到該圖時,就產(chǎn)生了很多困擾,“Aware,BeanPostProcessor......這些都是什么??!而且這么多步驟,太多了,該怎么記?。 ?。

其實要記憶該過程,還是需要我們先去理解,本文將從以下兩方面去幫助理解 Bean 的生命周期:

  1. 生命周期的概要流程:對 Bean 的生命周期進(jìn)行概括,并且結(jié)合代碼來理解;
  2. 擴(kuò)展點的作用:詳細(xì)介紹 Bean 生命周期中所涉及到的擴(kuò)展點的作用。

2. 生命周期的概要流程

Bean 的生命周期概括起來就是?4 個階段:

  1. 實例化(Instantiation);
  2. 屬性賦值(Populate);
  3. 初始化(Initialization);
  4. 銷毀(Destruction)。

如何記憶 Spring Bean 的生命周期


  1. 實例化:第 1 步,實例化一個 bean 對象;
  2. 屬性賦值:第 2 步,為 bean 設(shè)置相關(guān)屬性和依賴;
  3. 初始化:第 3~7 步,步驟較多,其中第 5、6 步為初始化操作,第 3、4 步為在初始化前執(zhí)行,第 7 步在初始化后執(zhí)行,該階段結(jié)束,才能被用戶使用;
  4. 銷毀:第 8~10步,第8步不是真正意義上的銷毀(還沒使用呢),而是先在使用前注冊了銷毀的相關(guān)調(diào)用接口,為了后面第9、10步真正銷毀 bean 時再執(zhí)行相應(yīng)的方法。

下面我們結(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 接口有:

  1. BeanNameAware:注入當(dāng)前 bean 對應(yīng) beanName;
  2. BeanClassLoaderAware:注入加載當(dāng)前 bean 的 ClassLoader;
  3. BeanFactoryAware:注入 當(dāng)前BeanFactory容器 的引用。

其代碼實現(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 的方式注入的,但其作用仍是注入依賴。

  1. EnvironmentAware:注入 Enviroment,一般用于獲取配置屬性;
  2. EmbeddedValueResolverAware:注入 EmbeddedValueResolver(Spring EL解析器),一般用于參數(shù)解析;
  3. ApplicationContextAware(ResourceLoader、ApplicationEventPublisherAware、MessageSourceAware):注入 ApplicationContext 容器本身。

其代碼實現(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 BeanPostProcessor

BeanPostProcessor 是 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;????}}

常用場景有:

  1. 對于標(biāo)記接口的實現(xiàn)類,進(jìn)行自定義處理。例如3.1節(jié)中所說的ApplicationContextAwareProcessor,為其注入相應(yīng)依賴;再舉個例子,自定義對實現(xiàn)解密接口的類,將對其屬性進(jìn)行解密處理;
  2. 為當(dāng)前對象提供代理實現(xiàn)。例如 Spring AOP 功能,生成對象的代理類,然后返回。
//?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-method

InitializingBean 和 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 的生命周期:

  • 首先是實例化、屬性賦值、初始化、銷毀這 4 個大階段;
  • 再是初始化的具體操作,有 Aware 接口的依賴注入、BeanPostProcessor 在初始化前后的處理以及 InitializingBean 和 init-method 的初始化操作;
  • 銷毀的具體操作,有注冊相關(guān)銷毀回調(diào)接口,最后通過DisposableBean 和 destory-method 進(jìn)行銷毀。


來源:https://www./content-4-894501.html

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多