Spring6 當中 Bean 的生命週期的詳細解析:有五步,有七步,有十步

Rainbow-Sea發表於2024-05-01

1. Spring6 當中 Bean 的生命週期的詳細解析:有五步,有七步,有十步

@

目錄
  • 1. Spring6 當中 Bean 的生命週期的詳細解析:有五步,有七步,有十步
  • 每博一文案
    • 1.1 什麼是 Bean 的生命週期
    • 1.2 Bean 的生命週期 "五步"
    • 1.3 Bean 的生命週期 “七步”
    • 1.4 Bean 的生命週期 “十步”
  • 2. Bean的作用域不同,管理方式也將是不同的
    • 2.1 自己new的物件讓Spring管理
  • 3. 總結:
  • 4. 最後:


每博一文案

“這個世界本來就是這樣的,會認識形形色色的人,會遇到無法理解的惡意,
會感到失望,但是隻要過去了,你就會發現,那些帶著偏見自說自話的言論,
還有那些不能理解的惡意,都是在提醒我們不要成為那樣的人。
或許會焦慮,會不知所措,生活也不太如意,會感到絕望。但我想說:前路漫漫,需自身強大。”

世界就是如此複雜,生活也從不是盡如人意,但我還是希望你,
即使見過那些骯髒與不堪,也依然能保有一顆溫良的心。深淵可以凝視,但不要駐足。

只要心存光明,世界就不黑暗。

1.1 什麼是 Bean 的生命週期

Spring 其實就是一個管理 Bean 物件的工廠。它負責物件的建立,物件的銷燬等。

所謂的生命週期:簡單的來說:就是一個物件從建立開始到最終銷燬的整個過程。

  • 什麼時候建立Bean 物件 ?
  • 建立 Bean 物件的前後會呼叫什麼方法?
  • Bean 物件什麼時候銷燬?
  • Bean 物件的在銷燬前後會呼叫生命方法?

那麼我們為什麼要知道 Bean 的生命週期呢?

其實生命週期的本質是:在哪個時間節點上呼叫了哪個類當中的哪個方法。

我們需要充分的瞭解在這個生命線當中,都有哪些特殊的時間節點。

只有我們知道了特殊的時間節點都在哪裡了,這樣我們才可以確定程式碼的對應上需要該寫到哪裡。

有時,我們可能需要在某個特殊的時間點上執行一段特定的程式碼,從而滿足我們的需求,而這段程式碼可以放到哪個節點上,當生命線走到這裡的時候,自然會被呼叫。

1.2 Bean 的生命週期 "五步"

關於 Bean 生命週期的管理,我們可以參考Spring的原始碼的:AbstractAutowireCapableBeanFactory類的doCreateBean()方法。 想要進一步瞭解該原始碼內容的大家可以移步至✏️✏️✏️Spring6 當中的 Bean 迴圈依賴的詳細處理方案+原始碼解析-CSDN部落格

這裡的 Bean的生命週期“五步”是最基本,比較粗略的五步。

  1. 第一步:例項化 Bean
  2. 第二步:對 Bean 當中的屬性進行賦值
  3. 第三步:初始化 Bean
  4. 第四步:使用 Bean
  5. 第五步:銷燬 Bean

在這裡插入圖片描述

注意點:

  1. 其中的:第三步:初始化 Bean 需要我們透過在 spring.xml 配置檔案當中的 標籤當中透過 init-method= 屬性指定初始化方法 是哪一個方法
  2. 其中的:第四步:銷燬 Bean 也是需要我們透過在 spring.xml 配置檔案當中的 標籤當中的 destroy-method=性指定銷燬方法 是哪個方法

實踐測試:

準備工作:配置匯入 相關的 spring 框架,讓 Maven 幫我們匯入 spring的相關jar包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rainbowsea</groupId>
    <artifactId>spring6-006-bean-lifecycle-blog</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>


    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.11</version>
        </dependency>


        <!-- junit4 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

第一步: 定義一個 Bean 物件類,這裡我們就定義一個 User 的類,來進行測試。

在這裡插入圖片描述

在這裡插入圖片描述

package com.rainbowsea.bean;

public class User {
    private String name;

    public User() {
        System.out.println(" 第一步: User 無引數構造方法呼叫");
    }


    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("第二步: 為 User 這個 Bean 進行賦值操作");
    }


    /**
     * 這個方法需要自己寫,方法名隨意,但是注意寫好之後,要透過init-method 配給Spring框架,讓其知道這個東東
     */
    public void initUserBean() {
        System.out.println("第三步: 對 User Bean 物件進行一個初始化操作");
    }


    /**
     * 這個方法需要自己寫,方法名隨意,但是注意寫好之後,要透過destroy-method配給Spring框架,讓其知道這個東東
     */
    public void destroyUserBean() {
        System.out.println("第五步: 對 User Bean 物件進行一個銷燬操作");
    }





    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

第二步: 配置相關的 spring.xml 告訴 Spring 框架要做的事情。

在這裡插入圖片描述

上面我們說到,注意點是:

  1. 其中的:第三步:初始化 Bean 需要我們透過在 spring.xml 配置檔案當中的 標籤當中透過 init-method= 屬性指定初始化方法 是哪一個方法
  2. 其中的:第四步:銷燬 Bean 也是需要我們透過在 spring.xml 配置檔案當中的 標籤當中的 destroy-method=性指定銷燬方法 是哪個方法

在這裡插入圖片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--init-method指明Bean的初始化方法是哪個;destroy-method指明Bean的銷燬方法是哪個    -->
    <bean id="userBean" class="com.rainbowsea.bean.User" init-method="initUserBean" destroy-method="destroyUserBean">
        <property name="name" value="張三"></property> <!--set注入賦值-->
    </bean>
</beans>

第三步: 執行客戶端,模擬測試

注意點:

我們需要手動呼叫 ClassPathXmlApplicationContext類下面的 close() 方法,正常關閉spring容器才會執行銷燬方法。

在這裡插入圖片描述
在這裡插入圖片描述

package com.rainbowsea.test;

import com.rainbowsea.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanLifecycleTest {

    @Test
    public void testRegisterBean() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
        User userBean = applicationContext.getBean("userBean", User.class);
        System.out.println("第四步: 使用 User Bean 物件" + userBean);

        ClassPathXmlApplicationContext classPathXmlApplicationContext = (ClassPathXmlApplicationContext) applicationContext;
        // 注意點:這裡的 close()方法是,ClassPathXmlApplicationContext 類才有的,它的ApplicationContext 父類沒有。
        // 父類無法呼叫子類特有的方法,所以這裡我們需要強制型別轉換回來(向下轉型),為子類
        // 只有正常關閉spring容器才會執行銷燬方法
        classPathXmlApplicationContext.close();


    }
}
 

執行結果:

在這裡插入圖片描述

總結注意點:

    1. 第一:配置檔案中的init-method指定初始化方法。destroy-method指定銷燬方法
    2. 第二:只有正常關閉spring容器,bean的銷燬方法才會被呼叫。
    3. 第三:ClassPathXmlApplicationContext類才有close()方法。

1.3 Bean 的生命週期 “七步”

Bean 的生命週期分為“七步”: 是在五步的當中的:第三步初始化Bean 的前後新增上的,Bean 的後處理器。如果加上 Bean 後處理器的話,Bean 的生命週期就是 七步了。

具體七步如下:

  1. 第一步:例項化 Bean
  2. 第二步:對 Bean 當中的屬性進行賦值
  3. 第三步:執行 Bean 後處理器的 befor() 方法執行,具體的是:postProcessBeforeInitialization(Object bean, String beanName) 方法
  4. 第四步:初始化 Bean
  5. 第五步:執行 Bean 後處理器的 after() 方法執行,具體的是 postProcessAfterInitialization(Object bean, String beanName) 方法
  6. 第六步:使用 Bean
  7. 第七步:銷燬 Bean

在這裡插入圖片描述

第一步:關於 Bean 的後處理器的編寫:

關於: bean的後處理器的編寫:

編寫 bean 後處理器,就是讓一個類實現 implements BeanPostProcessor 介面類,同時並且重寫其中的before(postProcessBeforeInitialization())和after(postProcessAfterInitialization())方法:

在這裡插入圖片描述
BeanPostProcessor 介面有,兩個預設的方法,這兩個方法,便是我們需要重寫的,來實現我們自己的要的功能。

@Nullable
// 在 Bean 初始化之前被呼叫
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

@Nullable
// 在 Bean 初始化之後就被呼叫
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

其中兩個引數的作用含義分別是:

在這裡插入圖片描述

    1. Object bean 是該對應的 bean 的物件
    2. String beanName 是該對應 bean 的在spring.xml配置檔案當中 id的名字。

    在這裡插入圖片描述

這裡我們定義一個MyBeanPostProcessor 類作為 Bean 後處理器 實現該 implements BeanPostProcessor 介面,並重寫其中的兩個預設方法。

在這裡插入圖片描述



import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // Object bean 是 該對應的 bean 的物件
        // String beanName 是該對應 bean 的在配置檔案當中 id
        System.out.println("第三步:  Bean 初始化之前執行before()方法");

        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // Object bean 是 該對應的 bean 的物件
        // String beanName 是該對應 bean 的在配置檔案當中 id
        System.out.println("第五步:  Bean 初始化之後執行after() 方法");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

第二步:將 Bean 後處理器配置到 spring.xml 檔案當中去,告知 Spring 框架,同時進行管理。

在這裡插入圖片描述

大家需要注意的是:該配置Bean後處理器。這個後處理器將作用於當前整個配置檔案中所有的bean。

在這裡插入圖片描述

也就是作用於當前這個名為 "spring6.xml" 檔案當中的,所配置的所有 bean 都會自動使用上這個我們配置的 bean 後處理器。關於這一點具體說明。我們後面會詳細說明的,大家放心。

第三步:模擬客戶端,執行程式:

在這裡插入圖片描述


import com.rainbowsea.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanLifecycleTest {

    @Test
    public void testRegisterBean() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
        User userBean = applicationContext.getBean("userBean", User.class);
        System.out.println("第六步: 使用 User Bean 物件" + userBean);

        ClassPathXmlApplicationContext classPathXmlApplicationContext = (ClassPathXmlApplicationContext) applicationContext;
        // 注意點:這裡的 close()方法是,ClassPathXmlApplicationContext 類才有的,它的ApplicationContext 父類沒有。
        // 父類無法呼叫子類特有的方法,所以這裡我們需要強制型別轉換回來(向下轉型),為子類
        // 只有正常關閉spring容器才會執行銷燬方法
        classPathXmlApplicationContext.close();


    }
}

上面我們提到了“這個 bean 後處理器的是作用於整個對應的 spring.xml 的配置檔案上的所有的 Bean” 的關於這一點,我們下面進行一個簡單的驗證一下。

我們再建立一個空的類,然後進行一個構造方法的注入,交給 Spring 框架進行管理,是否還是會執行 Bean 處理器。

在這裡插入圖片描述
在這裡插入圖片描述

執行測試:在這裡插入圖片描述

從執行結果上看,我們可以明顯的看出。這個Bean 後處理器是,作用於此 spring.xml 當中對應的整個 Bean 物件的 。簡單的來說:就是隻要你在某個其中的 spring.xml配置檔案當中,啟動了,並配置了對應的 Bean後處理器,那麼整個 spring.xml 配置檔案當中的所有的 Bean 物件都會自動啟動上該 Bean 後處理器。

1.4 Bean 的生命週期 “十步”

Bean的生命週期的“十步”就是更加的細化了更加的靈活了

讓我們一起來看一下,這所謂的十步,是在上面的七步當中的哪些節點當中,增加了那另外的三步。

十步是在下面這些位置,增加了另外的三步

  1. 首先在 Bean 後處理器的 befor ()執行的前後各自增加了一步,總共為兩步
    1. Bean 後處理器的 befor()執行前,增加了 檢查 Bean 是否實現了 Aware 的相關介面,並設定相關依賴。
    2. Bean 後處理器的 befor()執行後,增加了檢查 Bean 是否實現了 InitializingBean 介面,並呼叫介面當中的方法
  2. 最後一步,新增在了 銷燬 Bean 之前,增加了檢查 Bean 是否實現了 DisposableBean 介面,並呼叫介面當中的方法。

具體十步如下:

  1. 第一步:例項化 Bean
  2. 第二步:對 Bean 當中的屬性進行賦值
  3. 第三步: 檢查 Bean 是否實現了 Aware 的相關介面,並設定相關依賴。
    1. 其中Aware 的相關介面有三個分別是:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
  4. 第四步:執行 Bean 後處理器的 befor() 方法執行,具體的是:postProcessBeforeInitialization(Object bean, String beanName) 方法
  5. 第五步:檢查 Bean 是否實現了 InitializingBean 介面,並呼叫介面當中的方法
  6. 第六步:初始化 Bean
  7. 第七步:執行 Bean 後處理器的 after() 方法執行,具體的是 postProcessAfterInitialization(Object bean, String beanName) 方法
  8. 第八步:使用 Bean
  9. 第九步:檢查 Bean 是否實現了 DisposableBean 介面,並呼叫介面當中的方法。
  10. 第十步:銷燬 Bean

在這裡插入圖片描述

補充說明:

Aware相關的介面包括:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware

  • 當Bean實現了BeanNameAware,對應的方法是setBeanName(String name) :Spring會將Bean的名字傳遞給Bean。

  • 當Bean實現了BeanClassLoaderAware,對應的方法是setBeanClassLoader(ClassLoader classLoader) ; Spring會將載入該Bean的類載入器傳遞給Bean。

  • 當Bean實現了BeanFactoryAware,對應的方法是setBeanFactory(BeanFactory beanFactory); Spring會將Bean工廠物件傳遞給Bean。

  • 在這裡插入圖片描述
    InitializingBean 介面下對應的是:afterPropertiesSet () 方法。

  • 在這裡插入圖片描述
    DisposableBean 介面下的對應的是:destroy() 方法。

在這裡插入圖片描述

  • 測試以上10步,需要讓User類實現5個介面,並實現其中的所有方法:

    • BeanNameAware

    • BeanClassLoaderAware

    • BeanFactoryAware

    • InitializingBean

    • DisposableBean

第一步:定義 Bean 類,我們還是使用這個 User 空白類,進行測試。

第二步:讓 讓User類實現5個介面(BeanNameAware,BeanClassLoaderAware,BeanFactoryAware,InitializingBean,DisposableBean),並實現其中的所有方法:

在這裡插入圖片描述

package com.rainbowsea.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
    private String name;

    public User() {
        System.out.println("第一步: User 無引數構造方法呼叫");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("第五步:檢查Bean是否實現了InitializingBean 介面,並呼叫介面方法.afterPropertiesSet執行");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("第九步: 檢查 Bean是否實現了DisposableBean介面,並呼叫介面方法 destroy()  ");
    }
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("第三步:檢查是否實現了Aware的相關介面並呼叫其中的實現介面方法(): Bean 這個類的載入器" + classLoader);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("第三步:檢查是否實現了Aware的相關介面並呼叫其中的實現介面方法():  生產這個Bean的工廠物件是 " +beanFactory);
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("第三步:檢查是否實現了Aware的相關介面並呼叫其中的實現介面方法():  這個Bean的名稱是: " + name);
    }




    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("第二步: 為 User 這個 Bean 進行賦值操作");
    }


    /**
     * 這個方法需要自己寫,方法名隨意,但是注意寫好之後,要透過init-method 配給Spring框架,讓其知道這個東東
     */
    public void initUserBean() {
        System.out.println("第六步: 對 User Bean 物件進行一個初始化操作");
    }


    /**
     * 這個方法需要自己寫,方法名隨意,但是注意寫好之後,要透過destroy-method配給Spring框架,讓其知道這個東東
     */
    public void destroyUserBean() {
        System.out.println("第十步: 對 User Bean 物件進行一個銷燬操作");
    }





    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }


}

配置的 spring.xml 檔案資訊不變:保持和生命週期“七步”是一樣的,因為十步是基於七步的基礎上細化,新增的。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--配置Bean後處理器。這個後處理器將作用於當前配置檔案中所有的bean。-->
    <bean class="com.rainbowsea.bean.MyBeanPostProcessor"/>

    <!--init-method指明Bean的初始化方法是哪個;destroy-method指明Bean的銷燬方法是哪個    -->
    <bean id="userBean" class="com.rainbowsea.bean.User" init-method="initUserBean" destroy-method="destroyUserBean">
        <property name="name" value="張三"></property> <!--set注入賦值-->
    </bean>


</beans>

對應的 Bean 後處理也是不變的(和生命週期七步是一樣的),因為十步是基於七步的基礎上細化,新增的。

package com.rainbowsea.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // Object bean 是 該對應的 bean 的物件
        // String beanName 是該對應 bean 的在配置檔案當中 id
        System.out.println("第四步:  Bean 初始化之前執行before()方法");

        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // Object bean 是 該對應的 bean 的物件
        // String beanName 是該對應 bean 的在配置檔案當中 id
        System.out.println("第七步:  Bean 初始化之後執行after() 方法");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

最後:執行測試:

在這裡插入圖片描述

2. Bean的作用域不同,管理方式也將是不同的

Spring 根據 Bean 的作用域來選擇管理方式。

  1. 對於 singleton (spring 預設的單例)作用域的 Bean ,Spring 能夠精確地知道該 Bean 何時被建立,何時初始化完成的,以及何時被銷燬的,符合上述的生命週期的“五步”,“七步”,“十步” 的流程。
  2. 而對於 prototype(多例) 作用域的 Bean,Spring 只負責建立,當容器建立了 Bean 的例項後,Bean 的例項就交給了客戶端程式碼管理,Spring 容器將不再跟蹤其生命週期。不符合上述的生命週期的“五步”,“七步”,“十步” 的流程。

如下:我們把上述的User類的“Bean 的生命週期“十步”演示法當中的 ”spring.xml檔案中的配置scope設定為prototype。其他任何內容保持不變。進行演示

在這裡插入圖片描述

執行測試:

在這裡插入圖片描述

從執行結果上看:與之前的 bean 生命週期十步相比較看:我們可以明顯的發現。Spring 僅僅到bean 建立後,就不再管理了。而是交給客戶端進行自行管理了。spring 不再管理後面的操作了。

2.1 自己new的物件讓Spring管理

有些時候可能會遇到這樣的需求,某個java物件是我們自己new的,然後我們希望這個物件被Spring容器管理,怎麼實現?

準備工作,我們首先建立一個 bean 物件,這裡我們建立一個空的 Vip 類,作為 bean 。

在這裡插入圖片描述

我們需要透過 DefaultListableBeanFactory 這個物件,將我們 new 的物件交給 Spring 管理

再透過: DefaultListableBeanFactory 這個物件下的registerSingleton()方法,(這個交給 Spring 管理的bean的id/name 的命名,對於要交給spring管理的物件)
defaultListableBeanFactory.registerSingleton("vipBean",vip);

在這裡插入圖片描述

核心程式碼:

在這裡插入圖片描述

import com.rainbowsea.bean.User;
import com.rainbowsea.bean.Vip;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanLifecycleTest {

    @Test
    public void test() {
        // 第一步: 我們自己 new 一個物件,方便交給 spring 管理
        Vip vip = new Vip();
        System.out.println(vip);  // 列印一下地址,方便比較


        //  第二步:將以上自己 new 的這個物件納入 Spring 框架容器當中去管理,半路上交給 Spring來管理
        //  透過 DefaultListableBeanFactory 這個物件,將我們 new 的物件交給 Spring 管理
        DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
        // 透過: registerSingleton()方法,(這個交給 Spring 管理的bean的id/name 的命名,對於要交給spring管理的物件)
        
        defaultListableBeanFactory.registerSingleton("vipBean",vip);

        // 從Spring 容器中獲取:透過上述我們 registerSingleton()方法中定義的id,進行一個獲取
        Object vipBean = defaultListableBeanFactory.getBean("vipBean");
        System.out.println(vipBean);
        // 單例:地址是一樣的。

    }
}

我們是自己new 的物件,半路上交給 Spring 框架進行管理的,所以我們不需要配置spring.xml 的檔案上配置相關的 bean 資訊。

執行結果:

在這裡插入圖片描述

3. 總結:

  1. 熟悉Bean 的生命週期,各個時間節點上所能做的事情,可以讓我們更加靈活的掌握Spring上的運用,更加的靈活,實現我們的業務需要。
  2. Bean 的生命週期 "五步";注意點:初始化 Bean 需要我們透過在 spring.xml 配置檔案當中的 標籤當中透過 init-method= 屬性指定初始化方法 是哪一個方法;銷燬 Bean 也是需要我們透過在 spring.xml 配置檔案當中的 標籤當中的 destroy-method=性指定銷燬方法 是哪個方法
  3. Bean 的生命週期分為“七步”;是在五步的當中的:第三步初始化Bean 的前後新增上的,Bean 的後處理器。如果加上 Bean 後處理器的話,Bean 的生命週期就是 七步了。該配置Bean後處理器。這個後處理器將作用於當前整個配置檔案中所有的bean。
  4. Bean 的生命週期 “十步”;需要讓類實現5個介面(BeanNameAware,BeanClassLoaderAware,BeanFactoryAware,InitializingBean,DisposableBean),並實現其中的所有方法:
  5. singleton (spring 預設的單例)作用域的 Bean ,Spring 能夠精確地知道該 Bean 何時被建立,何時初始化完成的,以及何時被銷燬的,符合上述的生命週期的“五步”,“七步”,“十步” 的流程。
  6. Bean的作用域不同,管理方式也將是不同的;而對於 prototype(多例) 作用域的 Bean,Spring 只負責建立,不符合上述的生命週期的“五步”,“七步”,“十步” 的流程。 singleton (spring 預設的單例)作用域的 Bean 符合上述的生命週期的“五步”,“七步”,“十步” 的流程。
  7. 自己new的物件讓Spring管理(將以上自己 new 的這個物件納入 Spring 框架容器當中去管理,半路上交給 Spring來管理);透過: DefaultListableBeanFactory 這個物件下的registerSingleton()方法,(這個交給 Spring 管理的bean的id/name 的命名,對於要交給spring管理的物件)

4. 最後:

“在這個最後的篇章中,我要表達我對每一位讀者的感激之情。你們的關注和回覆是我創作的動力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會將你們的鼓勵留在心底,繼續在其他的領域奮鬥。感謝你們,我們總會在某個時刻再次相遇。”

在這裡插入圖片描述

相關文章