<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>

          【79期】別找了,回答Spring中Bean的生命周期,這里幫你總結(jié)好了!

          共 4839字,需瀏覽 10分鐘

           ·

          2020-11-03 17:53

          程序員的成長之路
          互聯(lián)網(wǎng)/程序員/技術(shù)/資料共享?
          關(guān)注


          閱讀本文大概需要 5?分鐘。

          來自:juejin.im/post/5a4ee1f6518825733e603fcb

          這一節(jié)準(zhǔn)備給大家講解Spring 容器中的Bean的生命周期。這一節(jié)我個人覺得還是比較實用的,在實際工作當(dāng)中經(jīng)常會用到這些知識來解決一些非常棘手的問題。

          ApplicationContext中Bean的生命周期

          先來張圖:
          大家看到這張圖肯定是一臉蒙蔽。不要著急,我來慢慢解釋:從getBean(…)為觸發(fā)點(diǎn),Spring容器的Bean生命周期就經(jīng)歷了圖中的生命周期,先分個類:
          • 圖中綠色箭頭的三個步驟(InstantiationAwareBeanPostProcessor)和粉紅色箭頭的兩個步驟(BeanPostProcessor)為容器級的生命周期接口,當(dāng)Spring每加載任何一個Bean到容器中時,這些接口都會起到如圖中的幾次調(diào)用。這兩個處理器叫做"容器級后處理器",他們的影響是全局的,能夠影響所有的Bean.

          • 圖中大紅色圓圈圈住的接口叫做"工廠級后處理器",類似的接口還有CustomEditorConfigurer,PropertyPlaceholderConfigurer等,這類接口只在上下文初始化的時候調(diào)用一次,其目的是完成一些配置文件的加工處理工作。

          • 剩下的就簡單了,屬于Bean級別的接口,專屬于某個Bean所有,每個Bean實例化的時候調(diào)用自己特有的。

          值得一提的是,無論是"容器級后處理器"還是"工廠級后處理器",他們都是可以配置多個的(如,配置兩個BeanPostProcessor),如果想控制他們的調(diào)用順序,實現(xiàn)一個org.springframework.core.Ordered接口即可。當(dāng)然了,一般不用,一般一類后處理器只有一個即可。
          重點(diǎn)強(qiáng)調(diào)!:
          這些接口的調(diào)用順序并不是一塵不變的,會隨便Spring的版本變動而變動,大家要做的是萬變不離其宗,知道能夠通過這些接口在Bean初始化的時做一些屬性上的操作。調(diào)用順序要根據(jù)具體的版本來自己測試。下面我會給大家來列一個例子:
          public?class?Student?implements?BeanFactoryAware,?BeanNameAware,
          ????????InitializingBean,?DisposableBean,ApplicationContextAware?
          {
          ????private?String?name;

          ????public?Student(String?name)?{
          ????????this.name?=?name;
          ????}

          ????public?String?getName()?{
          ????????return?name;
          ????}

          ????public?void?setName(String?name)?{
          ????????this.name?=?name;
          ????}

          ????@Override
          ????public?void?setBeanFactory(BeanFactory?beanFactory)?throws?BeansException?{
          ????????System.out.println("BeanFactoryAware......");
          ????}

          ????@Override
          ????public?void?setBeanName(String?s)?{
          ????????System.out.println("BeanNameAware......");
          ????}

          ????@Override
          ????public?void?destroy()?throws?Exception?{
          ????????System.out.println("DisposableBean......");
          ????}

          ????@Override
          ????public?void?afterPropertiesSet()?throws?Exception?{
          ????????System.out.println("InitializingBean......");
          ????}

          ????@Override
          ????public?void?setApplicationContext(ApplicationContext?applicationContext)?throws?BeansException?{
          ????????System.out.println("ApplicationContextAware......");
          ????}
          }
          BeanFactoryPostProcessor:
          public?class?MyBeanFactoryPostProcessor?implements?BeanFactoryPostProcessor?{

          ????public?MyBeanFactoryPostProcessor()?{
          ????????super();
          ????????System.out.println("這是BeanFactoryPostProcessor實現(xiàn)類構(gòu)造器??!");
          ????}

          ????@Override
          ????public?void?postProcessBeanFactory(ConfigurableListableBeanFactory?arg0)
          ????????????throws?BeansException?
          {
          ????????System.out.println("BeanFactoryPostProcessor調(diào)用postProcessBeanFactory方法");
          ????????BeanDefinition?bd?=?arg0.getBeanDefinition("student");
          ????????MutablePropertyValues?propertyValues?=?bd.getPropertyValues();
          ????????//配置文件中的信息在加載到Spring中后以BeanDefinition的形式存在.在這里又可以更改BeanDefinition,所以可以理解為更改配置文件里面的內(nèi)容
          //????????propertyValues.add("zdy","123");
          ????}

          }
          BeanPostProcessor:
          public?class?MyBeanPostProcessor?implements?BeanPostProcessor?{

          ????public?MyBeanPostProcessor()?{
          ????????super();
          ????????System.out.println("這是BeanPostProcessor實現(xiàn)類構(gòu)造器!!");
          ????}

          ????@Override
          ????public?Object?postProcessAfterInitialization(Object?arg0,?String?arg1)
          ????????????throws?BeansException?
          {
          ????????System.out.println("BeanPostProcessor接口方法After對屬性進(jìn)行更改!");
          ????????return?arg0;
          ????}

          ????@Override
          ????public?Object?postProcessBeforeInitialization(Object?arg0,?String?arg1)
          ????????????throws?BeansException?
          {
          ????????System.out.println("BeanPostProcessor接口方法Before對屬性進(jìn)行更改!");
          ????????return?arg0;
          ????}
          }
          InstantiationAwareBeanPostProcessorAdapter:
          public?class?MyInstantiationAwareBeanPostProcessor?extends
          ????????InstantiationAwareBeanPostProcessorAdapter?
          {

          ????public?MyInstantiationAwareBeanPostProcessor()?{
          ????????super();
          ????????System.out.println("這是InstantiationAwareBeanPostProcessorAdapter實現(xiàn)類構(gòu)造器?。?);
          ????}

          ????//?接口方法、實例化Bean之前調(diào)用
          ????@Override
          ????public?Object?postProcessBeforeInstantiation(Class?beanClass,
          ?????????????????????????????????????????????????String?beanName)
          ?throws?BeansException?
          {
          ????????System.out.println("InstantiationAwareBeanPostProcessor調(diào)用Before方法");
          ????????return?null;
          ????}

          ????//?接口方法、實例化Bean之后調(diào)用
          ????@Override
          ????public?Object?postProcessAfterInitialization(Object?bean,?String?beanName)
          ????????????throws?BeansException?
          {
          ????????System.out.println("InstantiationAwareBeanPostProcessor調(diào)用Ater方法");
          ????????return?bean;
          ????}

          ????//?接口方法、設(shè)置某個屬性時調(diào)用
          ????@Override
          ????public?PropertyValues?postProcessPropertyValues(PropertyValues?pvs,
          ????????????????????????????????????????????????????PropertyDescriptor[]?pds,?Object?bean,?String?beanName)

          ????????????throws?BeansException?
          {
          ????????System.out.println("InstantiationAwareBeanPostProcessor調(diào)用postProcessPropertyValues方法");
          ????????return?pvs;
          ????}
          }
          然后我們的Main方法:
          public?class?App?
          {

          ????public?static?void?main(?String[]?args?)
          ????
          {

          ????????ApplicationContext?ac?=new?ClassPathXmlApplicationContext("applicationContext.xml");
          ????????Student?stu?=?(Student)?ac.getBean("student");
          ????????stu.setName("wangwu");
          ????}
          }
          Spring文件最簡單:(注意要把我們自己定義的處理器全部加到容器里去)

          <beans
          ????<bean?id="student"?class="com.zdy.Student">

          ????????<constructor-arg?value="zhangsan"/>
          ????bean>

          ????<bean?id="myBeanFactoryPostProcessor"?class="com.zdy.MyBeanFactoryPostProcessor">bean>
          ????<bean?id="myInstantiationAwareBeanPostProcessor"?class="com.zdy.MyInstantiationAwareBeanPostProcessor">bean>
          ????<bean?id="myBeanPostProcessor"?class="com.zdy.MyBeanPostProcessor">bean>
          beans>
          然后run一下子,看結(jié)果:
          這是BeanFactoryPostProcessor實現(xiàn)類構(gòu)造器??!
          BeanFactoryPostProcessor調(diào)用postProcessBeanFactory方法
          這是InstantiationAwareBeanPostProcessorAdapter實現(xiàn)類構(gòu)造器!!
          這是BeanPostProcessor實現(xiàn)類構(gòu)造器!!
          InstantiationAwareBeanPostProcessor調(diào)用Before方法
          InstantiationAwareBeanPostProcessor調(diào)用postProcessPropertyValues方法
          BeanNameAware......
          BeanFactoryAware......
          ApplicationContextAware......
          BeanPostProcessor接口方法Before對屬性進(jìn)行更改!
          InitializingBean......
          InstantiationAwareBeanPostProcessor調(diào)用Ater方法
          BeanPostProcessor接口方法After對屬性進(jìn)行更改!
          好了,其實大致流程就說完了,我大致針對Bean的生命周期說一下:Spring為了盡可能的把自己內(nèi)部的東西機(jī)制暴露出來給用戶使用,所以在Bean創(chuàng)建的過程中加了很多機(jī)制,通過所謂的"處理器"Processor暴露出來,然后處理器都有自己的順序,我們需要做的就是定義好處理器的邏輯,然后注冊到Sprinhg容器中,Spring就會調(diào)用了。
          其次,還有一種方式,就是讓我們的Bean實現(xiàn)一些接口(類似于ApplicationContextAware),通過這種方式,在Bean初始化的某個步驟調(diào)用接口定義好的方法來傳入一些信息進(jìn)來,像ApplicationContextAware就把ApplicationContext給傳給我們了。
          然后我給大家說幾個實用點(diǎn)的知識點(diǎn),大家記著,用到時回來翻一翻就可以了:
          1. 上面的生命周期流程圖,時候的時候注意調(diào)用先后順序,避免屬性被覆蓋的現(xiàn)象。

          2. BeanFactoryPostProcessor 主要是在Spring剛加載完配置文件,還沒來得及初始化Bean的時候做一些操作。比如篡改某個Bean在配置文件中配置的內(nèi)容。

          3. InstantiationAwareBeanPostProcessorAdapter 基本沒什么鳥用,Bean初始化后,還沒有設(shè)置屬性值時調(diào)用,和BeanFactoryPostProcessor一樣,可以篡改配置文件加載到內(nèi)存中的信息。

          4. ApplicationContextAware:用處很大,注入了ApplicationContext到Bean中。

          5. InitializingBean:有用處,可以在Bean屬性全部改完之后,再做一些定制化操作。

          6. BeanPostProcessor:沒什么用,Spring框架內(nèi)部使用的比較猛,像什么AOP,動態(tài)代理,都是在這搞事。后期有時間和大家分析。

          7. 其他的像什么init-method,destroy方法,基本都是個擺設(shè)。。我是沒怎么用過,只知道有這么回事。

          結(jié)語

          好了,Bean的生命周期算上和大家分享完了,其實沒什么東西,大家知道有這么回事,能用到"后處理器"搞事的時候回來大致看下順序即可。其次就是一些Bean實現(xiàn)的接口,最常用的就是(ApplicationContextAware和InitializingBean)了。還有就是BeanPostProcessor,因為這個接口的方法里會把Bean實體以O(shè)bject傳進(jìn)去。
          所以可以進(jìn)行一些屬性上的操作。其實說實在的,程序員用的比較少??蚣軆?nèi)部用的多。OK,這篇講的其實比較糙,主要是因為沒什么東西可講,Over,Have a good day !

          推薦閱讀:

          【78期】別找了,Java集合面試問題這里幫你總結(jié)好了!

          【77期】這一道面試題就考驗了你對Java的理解程度

          【75期】面試官:說說Redis的過期鍵刪除策略吧?。ǜ哳l)

          5T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機(jī),樹莓派,等等。在公眾號內(nèi)回復(fù)「2048」,即可免費(fèi)獲取??!

          微信掃描二維碼,關(guān)注我的公眾號

          朕已閱?

          瀏覽 24
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(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成人永久网站 | 亚洲AV人人澡人人爽人人乐 | 99青青五月丁香 | 真实国产亂伦免费看 | 影音先锋av资源网站 |