乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      如何記憶 Spring Bean 的生命周期

       印度阿三17 2021-03-17

      1. 引言

      “請(qǐng)你描述下 Spring Bean 的生命周期?”,這是面試官考察 Spring 的常用問(wèn)題,可見(jiàn)是 Spring 中很重要的知識(shí)點(diǎn)。

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

      如何記憶 Spring Bean 的生命周期


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

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

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

      2. 生命周期的概要流程

      Bean 的生命周期概括起來(lái)就是?4 個(gè)階段:

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

      如何記憶 Spring Bean 的生命周期


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

      下面我們結(jié)合代碼來(lái)直觀的看下,在 doCreateBean() 方法中能看到依次執(zhí)行了這 4 個(gè)階段:

      //?AbstractAutowireCapableBeanFactory.javaprotected
      ?Object?doCreateBean(final
      ?String
      ?beanName
      ,?
      final
      ?RootBeanDefinition
      ?mbd
      ,?
      final
      ?@Nullable
      ?
      Object
      []
      ?args
      )
      ????throws
      ?BeanCreationException?
      {????
      //?1.?實(shí)例化
      ????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.?銷(xiāo)毀-注冊(cè)回調(diào)接口
      ????try
      ?{
      ????????registerDisposableBeanIfNecessary
      (
      beanName
      ,
      ?bean
      ,
      ?mbd
      );
      ????
      }????
      return
      ?exposedObject
      ;
      }

      由于初始化包含了第 3~7步,較復(fù)雜,所以我們進(jìn)到 initializeBean() 方法里具體看下其過(guò)程(注釋的序號(hào)對(duì)應(yīng)圖中序號(hào)):

      //?AbstractAutowireCapableBeanFactory.javaprotected?Object?initializeBean(final?String?beanName,?final?Object?bean,?@Nullable?RootBeanDefinition?mbd)?{????//?3.?檢查?Aware?相關(guān)接口并設(shè)置相關(guān)依賴(lài)????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.?若實(shí)現(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() 方法中會(huì)檢查 InitializingBean 接口和 init-method 方法,銷(xiāo)毀的過(guò)程也與其類(lèi)似:

      //?DisposableBeanAdapter.javapublic?void?destroy()?{????//?9.?若實(shí)現(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í)行過(guò)程,而我們記憶其過(guò)程便可以從這 4 個(gè)階段出發(fā),實(shí)例化、屬性賦值、初始化、銷(xiāo)毀。其中細(xì)節(jié)較多的便是初始化,涉及了 Aware、BeanPostProcessor、InitializingBean、init-method 的概念。這些都是 Spring 提供的擴(kuò)展點(diǎn),其具體作用將在下一節(jié)講述。

      3. 擴(kuò)展點(diǎn)的作用

      3.1 Aware 接口

      若 Spring 檢測(cè)到 bean 實(shí)現(xiàn)了 Aware 接口,則會(huì)為其注入相應(yīng)的依賴(lài)。所以通過(guò)讓bean 實(shí)現(xiàn) Aware 接口,則能在 bean 中獲得相應(yīng)的 Spring 容器資源。

      Spring 中提供的 Aware 接口有:

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

      其代碼實(shí)現(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);????????}????}}

      以上是針對(duì) BeanFactory 類(lèi)型的容器,而對(duì)于 ApplicationContext 類(lèi)型的容器,也提供了 Aware 接口,只不過(guò)這些 Aware 接口的注入實(shí)現(xiàn),是通過(guò) BeanPostProcessor 的方式注入的,但其作用仍是注入依賴(lài)。

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

      其代碼實(shí)現(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ò)展點(diǎn),其可作用于容器中所有 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;????}}

      常用場(chǎng)景有:

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

      3.3 InitializingBean 和 init-method

      InitializingBean 和 init-method 是 Spring 為?bean 初始化提供的擴(kuò)展點(diǎn)。

      InitializingBean接口 的定義如下:

      public?interface?InitializingBean?{????void?afterPropertiesSet()?throws?Exception;}

      在 afterPropertiesSet() 方法寫(xiě)初始化邏輯。

      指定 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 與上述類(lèi)似,就不描述了。

      4. 總結(jié)

      最后總結(jié)下如何記憶 Spring Bean 的生命周期:

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


      來(lái)源:https://www./content-4-894501.html

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

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多