<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          《面試1v1》SpringBean生命周期

          共 5289字,需瀏覽 11分鐘

           ·

          2023-05-31 13:38

          我是 javapub,一名 Markdown 程序員從?????,八股文種子選手。

          面試官:小伙子,聽說你對 Spring Bean 生命周期比較熟悉,我們聊聊吧。Spring Bean 都有哪些生命周期階段?

          候選人: Spring Bean 的生命周期可以分為 5 個階段:

          1. 實例化(Instantiation):Spring 使用 BeanDefinition 中的信息實例化 Bean。
          2. 屬性賦值(Dependency injection):Spring 將 BeanDefinition 中配置的屬性值注入到 Bean 中。
          3. 初始化前階段(Post-Construct):如果 Bean 實現(xiàn)了 InitializingBean 接口,會調(diào)用 afterPropertiesSet() 方法。
          4. 初始化階段(Initialization):如果在 BeanDefinition 中配置了 init-method,會調(diào)用該方法。
          5. 銷毀階段(Destruction):如果 Bean 實現(xiàn)了 DisposableBean 接口,會調(diào)用 destroy() 方法。如果配置了 destroy-method,會調(diào)用該方法。

          面試官:聰明!初始化方法有哪些?在源碼層面,Spring 是如何調(diào)用這些方法的?

          候選人: Spring Bean 提供了 3 種初始化方法:

          1. @PostConstruct:這是 JSR-250 注解,Spring 會在 Bean 初始化后自動調(diào)用被此注解標(biāo)注的方法。
          2. InitializingBean 接口:這個接口只有一個方法 afterPropertiesSet(),Spring 會在 Bean 初始化后調(diào)用該方法。
          3. 自定義 init-method:在 BeanDefinition 中配置 init-method 屬性,指向 Bean 中的某個方法名,Spring 會在 Bean 初始化后調(diào)用這個方法。

          在源碼層面,這些方法的調(diào)用是在 AbstractAutowireCapableBeanFactoryinitializeBean 方法中實現(xiàn)的:

                
                protected?Object?initializeBean(final?String?beanName,?final?Object?bean,?@Nullable?RootBeanDefinition?mbd)?{
          ????//?...
          ????????
          ????//?1.?處理?PostConstruct?注解
          ????if?(mbd?==?null?||?!mbd.isExternallyManagedInitMethod("afterPropertiesSet"))?{
          ????????//?2.?實現(xiàn)了?InitializingBean?接口的?Bean?會調(diào)用?afterPropertiesSet()?方法
          ????????if?(bean?instanceof?InitializingBean)?{
          ????????????((InitializingBean)?bean).afterPropertiesSet();
          ????????}
          ????}

          ????//?3.?調(diào)用自定義的?init-method?
          ????if?(mbd?!=?null?&&?bean.getClass()?!=?NullBean.class)?{
          ????????String?initMethodName?=?mbd.getInitMethodName();
          ????????if?(StringUtils.hasLength(initMethodName)?&&?
          ????????????!(bean?instanceof?InitializingBean?&&?"afterPropertiesSet".equals(initMethodName))?&&
          ????????????!mbd.isExternallyManagedInitMethod(initMethodName))?{
          ????????????????Method?initMethod?=?bean.getClass().getMethod(initMethodName);
          ????????????????initMethod.invoke(bean);
          ????????}
          ????}
          }

          面試官:不錯,你對 Spring Bean 的初始化過程很清楚!那銷毀方法哪些?原理又是什么?

          候選人: Spring Bean 提供了 2 種銷毀方法:

          1. DisposableBean 接口:實現(xiàn)這個接口的 Bean 會調(diào)用 destroy() 方法。
          2. 自定義 destroy-method:在 BeanDefinition 中配置 destroy-method 屬性,指向 Bean 中的某個方法名,Spring 會在 Bean 銷毀前調(diào)用這個方法。

          在源碼層面,這些方法的調(diào)用是在 AbstractAutowireCapableBeanFactorydestroyBean 方法中實現(xiàn)的:

                
                protected?void?destroyBean(String?beanName,?@Nullable?DisposableBean?bean)?{
          ????//?1.?實現(xiàn)了?DisposableBean?接口的?Bean?會調(diào)用?destroy()?方法
          ????if?(bean?!=?null)?{?
          ????????bean.destroy();
          ????}

          ????//?2.?調(diào)用自定義的?destroy-method
          ????String?destroyMethodName?=?getDestroyMethodName(beanName);
          ????if?(destroyMethodName?!=?null)?{
          ????????Method?destroyMethod?=?null;
          ????????try?{
          ????????????//?獲取?destroy-method?方法對象
          ????????????destroyMethod?=?bean.getClass().getMethod(destroyMethodName);?
          ????????}?catch?(NoSuchMethodException?ex)?{
          ????????????throw?new?BeanDefinitionStoreException(...);
          ????????}
          ????????
          ????????//?調(diào)用方法
          ????????try?{
          ????????????if?(destroyMethod?!=?null)?{
          ????????????????destroyMethod.invoke(bean);
          ????????????}
          ????????}?catch?(...)?{
          ????????????throw?new?BeanCreationException(...);?
          ????????}
          ????}?
          ????
          }

          面試官:棒!最后,Spring Bean 的作用域都有哪些?如何控制 Bean 的生命周期?

          候選人: Spring Bean 的作用域有 5 種:

          1. singleton:單例,整個 Spring 容器中只有一個 Bean 實例。
          2. prototype:原型,每次獲取 Bean 都會創(chuàng)建一個新的實例。
          3. request:每個 HTTP 請求都會創(chuàng)建一個 Bean 實例。
          4. session:每個 HTTP 會話都會創(chuàng)建一個 Bean 實例。
          5. global-session:每個全局 HTTP 會話都會創(chuàng)建一個 Bean 實例。

          我們可以通過 scope 屬性控制 Bean 的作用域,從而影響其生命周期:

                
                
                  <bean?id="..."?class="..."?scope="prototype"/>
                  

          此外,我們還可以自定義 Bean 的初始化和銷毀方法,在 Bean 作用域開始和結(jié)束時觸發(fā):

                
                
                  <bean?id="..."?class="..."?scope="prototype"?
          ????init-method="start"?destroy-method="end">

          </bean>

          這樣我們就可以在 start() 方法中執(zhí)行初始化邏輯,在 end() 方法中執(zhí)行清理工作,從而精確控制 Bean 的生命周期。

          面試官:很全面,佩服佩服!如果再給你一個機(jī)會,你覺得還可以在哪些方面加深對 Spring Bean 生命周期的理解?

          候選人: 這里有幾個方面可以進(jìn)一步加深對 Spring Bean 生命周期的理解:

          1. BeanPostProcessor:這個接口可以監(jiān)聽 Bean 的初始化前后,提供了擴(kuò)展點可以在 Bean 初始化前后進(jìn)行一些處理。這也是 Spring AOP 的底層原理之一。
          2. 了解 BeanFactoryPostProcessor:這個接口可以監(jiān)聽 BeanDefinition 的加載,可以在 Bean 實例化前修改 BeanDefinition 的屬性。
          3. 理解 Bean 的加載時機(jī):在 Spring 容器啟動時,默認(rèn)會立即加載 singleton 作用域的 Bean,而其他作用域的 Bean 會延遲加載, singleton 作用域的 Bean 也支持延遲加載。這就要涉及到Spring 的 lazy-init 屬性設(shè)置。
          4. 了解 Bean 為什么要有不同的作用域:每個作用域適合的場景是什么,選擇不同作用域會對 Bean 的生命周期產(chǎn)生怎樣的影響。
          5. 了解 Bean 之間的依賴關(guān)系對生命周期的影響:比如 A ?Bean 的初始化依賴 B Bean,那么 A Bean 的初始化也會延遲到 B Bean 初始化完畢后。這涉及到 Spring 的 depends-on 屬性配置。
          6. 了解自定義初始化和銷毀方法的具體應(yīng)用場景:什么情況下需要自定義這些方法,能在方法中完成什么樣的邏輯處理。
          7. 探索 BeanPostProcessor 和 BeanFactoryPostProcessor 的具體應(yīng)用:比如 Spring AOP、Spring 事件發(fā)布者等機(jī)制的實現(xiàn)。綜上,要全面理解 Spring Bean 的生命周期,除了知道每個階段的調(diào)用外,還需要對很多這個過程涉及到的其他知識點進(jìn)行深入學(xué)習(xí)和理解,這需要不斷實踐和總結(jié)。但只要把這些要點都串聯(lián)起來,對 Spring Bean 的生命周期控制就會很得心應(yīng)手了。

          面試官:非常棒,這些點精彩極了!你的回答已經(jīng)很全面和深入,對 Spring Bean 生命周期有清晰理解,這些又是常見的面試重點,我相信面試一定會取得很好的表現(xiàn),加油!我們就聊到這里,很高興與你的交流,謝謝!


          5071edf20e9547ae433cd51333a16dfb.webp


          最近我在更新《面試1v1》系列文章,主要以場景化的方式,講解我們在面試中遇到的問題,致力于讓每一位工程師拿到自己心儀的offer,感興趣可以關(guān)注公眾號JavaPub追更!

          《面試1v1》連載中...

          瀏覽 59
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操逼在线 | 天天撸视频 夜夜撸视频 | 国产精品——色哟哟 | 天天日AV片 | 婷婷亚洲性爱 |