工作5年了還說不清bean生命周期?大廠offer怎麼可能給你!

  • 2020 年 3 月 17 日
  • 筆記

第一,這絕對是一個面試高頻題。

 

比第一還重要的第二,這絕對是一個讓人愛恨交加的面試題。為什麼這麼說?我覺得可以從三個方面來說:

  1. 先說會不會。看過源碼的人,這個不難;沒看過源碼的人,無論是學、硬背、還是說,絕對是一個坎。

  2. 再說考察點。這個問題還是比較開放的。可以用三五句話講出來,也可以揪着面試官聊半個小時。

  3. 最後說效果。說的不好,絕對“狠減分”;說的好了,也絕對“狠加分”。

     

所以說,遇到這個問題,要麼顫抖着死去,要麼就需要你有強大的忍住不笑了的能力(這個梗可懂)。

 

好吧好吧,既然都這麼“硬核”了,我們沒有理由不拿下。

 

接下來我嘗試站在面試官的角度來分析,“他們”想考察的知識點,摸清了套路,再設法一點點的去“餵飽”面試官。

 

第一層:簡單回答問題

 

面試官心裏分析:

 

作為面試官,我提這個問題,想知道你是否有看源碼的習慣或者說經歷。通過你的回答,我能初步判斷出,你平時是滿足於“CRUD”完成需求?還是有好奇心去尋找底層是如何實現的?進而我也就能預判,如果招你進來,是一個偏執行性的人,還是能在團隊中承擔更多的責任,能主動探究和發現問題。

 

其實這相當於面試官給我們畫好的圈子,只要我們提出幾個關鍵點,即可證明我們看過。

 

非主流標準答案:

 

part1.

在真正開始bean的生命周期之前,會讀取資源文件,生成BeanDefinition對象。BeanDefinition是bean的前生,bean是BeanDefinition的今世。BeanDefinition除了像Class那樣描述了屬性方法之類的外,還描述bean的其他特性,比如,是否單例,依賴關係等

 

part2.

在整個生命周期中,主要就是兩件事,bean的創建和賦值以及依賴關係的注入;通過各個擴展點豐富bean的能力,比如BeanFactoryPostProcessor、BeanPostProcessor等。

 

第二層:展露亮點

 

面試官心裏分析

 

僅僅達到目標我們就滿足了嗎?當然不能,我們追求的,是卓越!如果我們能藉助一個類似流程圖之類的框架,把bean生命周期在最短的時間內,清晰,簡明的描述出來,這就是讓面試官眼前一亮的亮點。我會覺得你,除了好奇心和自驅力外,理解和總結能力也不錯,以後我們稱為同事溝通時,不會讓我覺得經常雞同鴨講(別告訴我你沒遇到過這種人,給他把方案講三兩遍,一直在點頭,等做出來的活發現還是南轅北轍,這絕對不是笑話)。

 

非主流標準答案:

 

part1.

bean的生命周期,主要經歷4個階段,4類擴展。分別結合兩張圖來說明,先來看下4個階段:

 

說明:怎麼理解這個過程呢?

 

  •  類比我們自己構造一個對象,也是先調用構造函數創建,然後通過setter為屬性賦值。分別對應了上圖中的【實例化】和【為Bean屬性賦值。

     

  • 這裡提了初始化環節,該環節對應執行的,是我們在定義bean(比如xml配置,比如註解中配置)時,配置的init方法。

     

  • 最後一個註銷,就更好理解了,在Java出現之前的C時代,是需要程序員自己管理內存的,那麼在分配內存創建對象後,是需要自己註銷對象釋放內存的。那麼既然已經在Java里了為什麼還要明確的有這個環節呢?我理解,作為框架,首先不能完全依賴GC來回收對象,這樣太被動了;另外,我都是框架了,框架二字意味着什麼?超強的整合能力!翻譯成人話就是,你想要的都在這,你想做什麼我都給你留了“後門”(接口)。,那當你想在這個環節搞點什麼事情的時候,卻發現我無能為力,豈不是尬了?

     

part2.

接下來再來看4類擴展。所謂擴展,首先我們簡單的理解下,無非就是提供了一系列的接口,你只要實現這些接口,就能在整個生命周期的某一個節點,執行你實現的方法邏輯,在這個方法里呢,可以拿到xxx對象(比如ApplicationContext,比如BeanDefinition,比如Bean等等);然後對這些對象做點什麼。還是來看下圖:

 

 

        

請看上圖,一個色系代表一類接口。

 

  1.  BeanFactoryPostProcessor接口,實現該接口可以拿到BeanDefinition,可以做修改。

     

  2. BeanPostProcessor接口,上圖中的InstantiationAwareBeanPostProcessor是其子接口,所以都歸為一類,都是和創建bean相關的。

     

  3. xxxAware接口,比如BeanNameAware,BeanFactoryAware,ApplicationContextAware,拿ApplicationContextAware來說,可以獲取當前上下文,然後進而拿到bean的實例,進行處理。

     

  4. xxxBean接口,有三個典型應用:

     

    1. FactoryBean:能生產bean的工廠。

    2. InitializingBean:初始化bean時候可進行擴展

    3. DiposibleBean:註銷bean時候可進行的擴展

第三層:釋放個人魅力

 

面試官心裏分析:

 

在講清流程的基礎上,如果你還能說一說框架在現實中的應用就更上一層樓了,我會認為你在工作中遇到問題時,工具箱里可選的工具更多。這無論從哪個角度來看,都能為團隊帶來正向的收益。

 

非主流標準答案:

 

    1.  BeanFactoryPostProcessor接口應用:

       

      1. mybatis,就是實現該接口的子接口,來通過mapper接口和xml中的sql,生成對應的類的BeanDefinition,這樣在使用時,就不用自己在寫連接數據庫,創建Session,執行查詢等等邏輯了。

         

      2. 在spring-boot中,入口方法在標註了@Configuration註解的類中,那這個方法是如何注入到spring中的呢?掃描標註該註解的邏輯,就是寫在實現了BeanFactoryPostProcessor接口的子接口的實例里。

         

      3. 還有直接實現BeanFactoryPostProcessor接口的,比如我們定義的DataSource中的佔位符,替換成實際的值。

         

    2. BeanPostProcessor接口的應用:

       

      1. AOP中需要在創建實例前判斷是否需要創建代理對象,相當於是阻斷了實例的創建。就是在實現InstantiationAwareBeanPostProcessor接口的實例中實現的,執行的是xxxBefore()方法

         

      2. 我們常用@AutoAware註解,引入一個bean,其依賴注入就是在InstantiationAwareBeanPostProcessor.xxxPropertyValues()方法中實現的。

         

其他的,暫時不在這裡列出,既然你看到了這篇文章,那麼也參與進來,我們一起補全。