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

          詳解Spring中Bean的作用域與生命周期

          共 5515字,需瀏覽 12分鐘

           ·

          2021-07-20 04:22

          ? ? ? ? ? ? ? ? ? ?

          摘要:在利用Spring進行IOC配置時,關(guān)于bean的配置和使用一直都是比較重要的一部分,同時如何合理的使用和創(chuàng)建bean對象,也是小伙伴們在學(xué)習(xí)和使用Spring時需要注意的部分,所以這一篇文章我就來和大家講一下有關(guān)Spring中bean的作用域和其生命周期。


          本文分享自華為云社區(qū)《詳解Spring中Bean的作用域與生命周期》,原文作者:灰小猿。


          在利用Spring進行IOC配置時,關(guān)于bean的配置和使用一直都是比較重要的一部分,同時如何合理的使用和創(chuàng)建bean對象,也是小伙伴們在學(xué)習(xí)和使用Spring時需要注意的部分,所以這一篇文章我就來和大家講一下有關(guān)Spring中bean的作用域和其生命周期。


          一、Bean的作用域


          首先我們來講一下有關(guān)于bean的作用域,


          一般情況下,我們書寫在IOC容器中的配置信息,會在我們的IOC容器運行時被創(chuàng)建,這就導(dǎo)致我們通過IOC容器獲取到bean對象的時候,往往都是獲取到了單實例的Bean對象,


          這樣就意味著無論我們使用多少個getBean()方法,獲取到的同一個JavaBean都是同一個對象,這就是單實例Bean,整個項目都會共享這一個bean對象。


          在Spring中,可以在<bean>元素的scope屬性里設(shè)置bean的作用域,以決定這個bean是單實例的還是多實例的。Scope屬性有四個參數(shù),具體的使用可以看下圖:


          f55996def2f301a9a564708d62b4c2ed.webp


          1、單實例Bean聲明


          默認情況下,Spring只為每個在IOC容器里聲明的bean創(chuàng)建唯一一個實例,整個IOC容器范圍內(nèi)都能共享該實例:所有后續(xù)的getBean()調(diào)用和bean引用都將返回這個唯一的bean實例。該作用域被稱為singleton它是所有bean的默認作用域。也就是單實例。


          為了驗證這一說法,我們在IOC中創(chuàng)建一個單實例的bean,并且獲取該bean對象進行對比:


          <!-- singleton單實例bean
          1、在容器創(chuàng)建時被創(chuàng)建
          2、只有一個實例
          -->
          <bean id="book02" class="com.spring.beans.Book" scope="singleton"></bean>


          測試獲取到的單實例bean是否是同一個:


          @Test
          public void test09() {
          // 單實例創(chuàng)建時創(chuàng)建的兩個bean相等
          Book book03 = (Book)iocContext3.getBean("book02");
          Book book04 = (Book)iocContext3.getBean("book02");
          System.out.println(book03==book04);
          }


          得到的結(jié)果是true;


          2、多實例Bean聲明


          而既然存在單實例,那么就一定存在多實例。我們可以為bean對象的scope屬性設(shè)置prototype參數(shù),以表示該實例是多實例的,同時獲取IOC容器中的多實例bean,再將獲取到的多實例bean進行對比,


          <!-- prototype多實例bean
          1、在容器創(chuàng)建時不會被創(chuàng)建,
          2、只有在被調(diào)用的時候才會被創(chuàng)建
          3、可以存在多個實例
          -->
          <bean id="book01" class="com.spring.beans.Book" scope="prototype"></bean>



          測試獲取到的多實例bean是否是同一個:


          @Test
          public void test09() {
          // 多實例創(chuàng)建時,創(chuàng)建的兩個bean對象不相等
          Book book01 = (Book)iocContext3.getBean("book01");
          Book book02 = (Book)iocContext3.getBean("book01");
          System.out.println(book01==book02);
          }


          得到的結(jié)果是false


          這就說明了,通過多實例創(chuàng)建的bean對象是各不相同的。


          在這里需要注意:


          同時關(guān)于單實例和多實例bean的創(chuàng)建也有不同,當(dāng)bean的作用域為單例時,Spring會在IOC容器對象創(chuàng)建時就創(chuàng)建bean的對象實例。而當(dāng)bean的作用域為prototype時,IOC容器在獲取bean的實例時創(chuàng)建bean的實例對象。


          二、Bean的生命周期


          1、bean的初始和銷毀


          其實我們在IOC中創(chuàng)建的每一個bean對象都是有其特定的生命周期的,在Spring的IOC容器中可以管理bean的生命周期,Spring允許在bean生命周期內(nèi)特定的時間點執(zhí)行指定的任務(wù)。如在bean初始化時執(zhí)行的方法和bean被銷毀時執(zhí)行的方法。


          Spring IOC容器對bean的生命周期進行管理的過程可以分為六步:


          1. 通過構(gòu)造器或工廠方法創(chuàng)建bean實例

          2. 為bean的屬性設(shè)置值和對其他bean的引用

          3. 調(diào)用bean的初始化方法

          4. bean可以正常使用

          5. 當(dāng)容器關(guān)閉時,調(diào)用bean的銷毀方法


          那么關(guān)于bean的初始和銷毀時執(zhí)行的方法又該如何聲明呢?


          首先我們應(yīng)該在bean類內(nèi)部添加初始和銷毀時執(zhí)行的方法。如下面這個javabean:


          package com.spring.beans;
          public class Book {
          private String bookName;
          private String author;
          /**
          * 初始化方法
          * */
          public void myInit() {
          System.out.println("book bean被創(chuàng)建");
          }

          /**
          * 銷毀時方法
          * */
          public void myDestory() {
          System.out.println("book bean被銷毀");
          }

          public String getBookName() {
          return bookName;
          }
          public void setBookName(String bookName) {
          this.bookName = bookName;
          }
          public String getAuthor() {
          return author;
          }
          public void setAuthor(String author) {
          this.author = author;
          }
          @Override
          public String toString() {
          return "Book [bookName=" + bookName + ", author=" + author + "]";
          }
          }



          這時我們在配置bean時,可以通過init-method和destroy-method 屬性為bean指定初始化和銷毀方法,


          <!-- 設(shè)置bean的生命周期
          destory-method:結(jié)束調(diào)用的方法
          init-method:起始時調(diào)用的方法
          -->
          <bean id="book01" class="com.spring.beans.Book" destroy-method="myDestory" init-method="myInit"></bean>


          這樣當(dāng)我們在通過IOC容器創(chuàng)建和銷毀bean對象時就會執(zhí)行相應(yīng)的方法,


          但是這里還是有一點需要注意:


          我們上面說了,單實例的bean和多實例的bean的創(chuàng)建時間是不同的,那么他們的初始方法和銷毀方法的執(zhí)行時間就稍稍有不同。


          • 單實例下 bean的生命周期


          容器啟動——>初始化方法——>(容器關(guān)閉)銷毀方法


          • 多實例下 bean的生命周期


          容器啟動——>調(diào)用bean——>初始化方法——>容器關(guān)閉(銷毀方法不執(zhí)行)


          2、bean的后置處理器


          什么是bean的后置處理器?bean后置處理器允許在調(diào)用初始化方法前后對bean進行額外的處理


          bean后置處理器對IOC容器里的所有bean實例逐一處理,而非單一實例。


          其典型應(yīng)用是:檢查bean屬性的正確性或根據(jù)特定的標準更改bean的屬性。


          bean后置處理器使用時需要實現(xiàn)接口:


          org.springframework.beans.factory.config.BeanPostProcessor。


          在初始化方法被調(diào)用前后,Spring將把每個bean實例分別傳遞給上述接口的以下兩個方法:


          postProcessBeforeInitialization(Object, String)調(diào)用前
          postProcessAfterInitialization(Object, String)調(diào)用后


          如下是一個實現(xiàn)在該接口的后置處理器:


          package com.spring.beans;

          import org.springframework.beans.BeansException;
          import org.springframework.beans.factory.config.BeanPostProcessor;
          /**
          * 測試bean的后置處理器
          * 在這里要注意一點是為了出現(xiàn)beanbeanName,而不是arg0arg1,需要綁定相應(yīng)的源碼jar
          * */
          public class MyBeanPostProcessor implements BeanPostProcessor {

          /**
          * postProcessBeforeInitialization
          * 初始化方法執(zhí)行前執(zhí)行
          * Object bean
          * String beanName xml容器中定義的bean名稱
          * */
          @Override
          public Object postProcessBeforeInitialization(Object bean, String beanName)
          throws BeansException {
          // TODO Auto-generated method stub
          System.out.println(""+ beanName+"】初始化方法執(zhí)行前...");
          return bean;
          }

          /**
          * postProcessAfterInitialization
          * 初始化方法執(zhí)行后執(zhí)行
          * Object bean
          * String beanName xml容器中定義的bean名稱
          * */
          @Override
          public Object postProcessAfterInitialization(Object bean, String beanName)
          throws BeansException {
          // TODO Auto-generated method stub
          System.out.println(""+ beanName+"】初始化方法執(zhí)行后...");
          return bean;
          }

          }



          將該后置處理器加入到IOC容器中:


          <!-- 測試bean的后置處理器 -->
          <bean id="beanPostProcessor" class="com.spring.beans.MyBeanPostProcessor"></bean>


          由于現(xiàn)在我們的bean對象是單實例的,所以容器運行時就會直接創(chuàng)建bean對象,同時也會執(zhí)行該bean的后置處理器方法和初始化方法,在容器被銷毀時又會執(zhí)行銷毀方法。我們測試如下:


              //*************************bean生命周期*****************
          // 由于ApplicationContext是一個頂層接口,里面沒有銷毀方法close,所以需要使用它的子接口進行接收
          ConfigurableApplicationContext iocContext01 = new ClassPathXmlApplicationContext("ioc1.xml");
          @Test
          public void test01() {
          iocContext01.getBean("book01");
          iocContext01.close();
          }


          運行結(jié)果:


          edf8426c101f3564a91ca6aa4399c017.webp


          2894ac29a18ad1c8dfed08ba40188812.webp


          總結(jié)一下后置處理器的執(zhí)行過程:


          1. 通過構(gòu)造器或工廠方法創(chuàng)建bean實例

          2. 為bean的屬性設(shè)置值和對其他bean的引用

          3. 將bean實例傳遞給bean后置處理器的postProcessBeforeInitialization()方法

          4. 調(diào)用bean的初始化方法

          5. 將bean實例傳遞給bean后置處理器的postProcessAfterInitialization()方法

          6. bean可以使用了

          7. 當(dāng)容器關(guān)閉時調(diào)用bean的銷毀方法


          所以添加bean后置處理器后bean的生命周期為:


          容器啟動——后置處理器的before...——>初始化方法——>后置處理器的after...———>(容器關(guān)閉)銷毀方法


          end


          *版權(quán)聲明:轉(zhuǎn)載文章和圖片均來自公開網(wǎng)絡(luò),版權(quán)歸作者本人所有,推送文章除非無法確認,我們都會注明作者和來源。如果出處有誤或侵犯到原作者權(quán)益,請與我們聯(lián)系刪除或授權(quán)事宜。


          長按識別圖中二維碼

          關(guān)注獲取更多資訊




          不點關(guān)注,我們哪來故事?



          d99cbc1da169d91a038973b30489b82c.webp

          點個再看,你最好看




          瀏覽 113
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  欧美成人黄色电影网站 | 欧美三级日本三级 | 国产A片大全 | 无码专区在线播放 | 大香蕉黄网 |