一步步剖析spring bean生命周期

来源:https://www.cnblogs.com/wangjiming/archive/2019/10/14/11669091.html
-Advertisement-
Play Games

關於spring bean的生命周期,是深入學習spring的基礎,也是難點,本篇文章將採用代碼+圖文結論的方式來闡述spring bean的生命周期, 本篇文章將闡述清楚下圖。 一 項目結構及源碼 1.程式目錄結構 2.applicationContext.xml 3.UserDao.java 二 ...


 關於spring bean的生命周期,是深入學習spring的基礎,也是難點,本篇文章將採用代碼+圖文結論的方式來闡述spring bean的生命周期,

本篇文章將闡述清楚下圖。

 

 一  項目結構及源碼

1.程式目錄結構

 2.applicationContext.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 class="com.demo.dao.UserDao" id="userDao" scope="singleton" init-method="myInit" destroy-method="myDestroy">
        <property name="userName" value="Alan_beijing"/>
    </bean>

    <bean class="com.demo.dao.MyBeanPostProcessor" id="myBeanPostProcessor"/>

</beans>

3.UserDao.java

package com.demo.dao;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.apache.log4j.Logger;

public class UserDao implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean,
        DisposableBean{

    private String userName;
    private int count = 0;

    public String getUserName() {
        return userName;
    }

    //2.屬性註入,註入屬性為userName
    public void setUserName(String userName) {
        count++;
        System.out.println(count + ":註入屬性userName="+userName);
        this.userName = userName;
    }

    //1.無參構造函數,實例化時調用該構造函數
    public UserDao() {
        count++;
        System.out.println(count + ":調用構造函數UserDao()");
    }

    //3.實現BeanNameAware,獲取bean id
    public void setBeanName(String s) {
        count++;
        System.out.println(count + ":調用setBeanName()獲取bean id,bean id=" + s);
    }

    //4.實現BeanFactoryAware,獲取bean工廠
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        count++;
        System.out.println(count + ":調用setBeanFactory()獲取bean工廠,beanFactory=" + beanFactory);
    }

    //5.實現ApplicationContextAware,獲取bean上下文
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        count++;
        System.out.println(count + ":調用setApplicationContext()獲取bean上下文,applicationContext=" + applicationContext);
    }

    //6.實現InitializingBean,獲取afterPropertiesSet
    public void afterPropertiesSet() throws Exception {
        count++;
        System.out.println(count + ":調用afterPropertiesSet()");
    }

    //7.自定義初始化方法myInit()
    public void myInit() {
        count++;
        System.out.println(count + ":調用自定義myInit()");
    }

    //8.實現DisposableBean,獲取destroy()
    public void destroy() throws Exception {
        count++;
        System.out.println(count + ":destroy()");
    }

    //9.自定義銷毀方法myDestroy()
    public void myDestroy() {
        count++;
        System.out.println(count + ":調用自定義destroy()");
    }
}
4.MyBeanPostProcessor.java
package com.demo.dao;

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

public  class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("=====調用postProcessBeforeInitialization()=====");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("=====調用postProcessAfterInitialization()=====");
        return bean;
    }
}

 二  測試代碼及測試結果

1.test.java

package com.demo.test;

import com.demo.dao.UserDao;
import org.junit.Test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

    @Test
    public void test() {
        //定義容器並初始化
        //ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        applicationContext.getBean(UserDao.class);
        //只有關閉容器時,才會調用destroy方法
        applicationContext.registerShutdownHook();
    }
}

2.測試結果

 三 分析

通過如上測試結果,bean生命周期流程大致如下:

 

 1.裝配bean

bean裝配為bean生命周期第一環節。所謂裝配bean,指將java對象轉換為bean的過程。在該示例中,UserDao.jave和MyBeanPostProcessor通過xml方式轉化為bean。

註意:spring框架支持四種方式裝配bean:xml方式,java代碼方式,自動裝配和混合裝配方式

2.載入applicationContext.xml並實例化

載入並實例化bean為bean生命周期的第二環節。本文示例通過ClassPathXmlApplicationContext()來載入並,當bean為singleton時,該過程就實例化對象,而不需要等待

調用applicationContext.getBean()獲取bean時才實例化對象,這與prototype是不一樣的。

3.屬性註入

bean屬性註入為bean生命周期第三環節,採用反射方式註入bean.

 

4.實現BeanNameAware,獲取bean id

該過程為bean生命周期的第四環節,實現該介面,可以獲取bean的id

 

5.實現BeanFactoryAware,獲取bean 工廠

該過程為bean生命周期第五環節,通過實現BeanFactoryAware獲取bean工廠

 6.實現ApplicationContextAware,獲取運用上下文

該過程為bean生命周期第六環節,通過實現ApplicationContextAware介面,獲取bean上下文

 7.調用Bean後置處理器,before

該過程為bean生命周期第七環節,通過實現後置處理器BeanPostProcessor獲取before和after,該過程是通過AOP方式實現的,在before和after之間,發生如下8,9過程。

8.實現InitializingBean的afterPropertiesSet(),獲取初始化方法

該過程為bean生命周期第八環節,通過實現InitializingBean,獲取afterPropertiesSet()

 9.調用自定義初始化方法,init-method

該過程為bean生命周期第九環節,實現自定義初始化方法

 10.調用Bean後置處理器after

該過程為bean生命周期第十環節,後置處理器最後環節

 11.關閉容器AbstractApplicationContext.registerShutDownHook()

該環節為bean生命周期第十一環節,關閉容器

 

 12.調用DisposableBean的destroy()

該過程為bean生命周期第十二環節,實現DisposableBean介面,調用destroy()

 13.調用定製化銷毀方法destroy-method

該過程為bean生命周期最後環節,調用自定義銷毀方法destroy-method

 三  版權區

  •   轉載博客,必須註明博客出處
  •    博主網址:http://www.cnblogs.com/wangjiming/
  •    如您有新想法,歡迎提出,郵箱:[email protected]
  •   專業.NET之家技術QQ群:490539956
  •   專業化Java之家QQ群:924412846
  •   有問必答QQ群:2098469527
  •   一對一技術輔導QQ:2098469527

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv ...
  • SSM的練習 : 1開發環境 資料庫:mysql5.5以上版本。 Jdk:1.7 開發環境:Eclipse mars2 Spring:4.2.4 Mybatis:3.2.7 Tomcat:7 2資料庫 資料庫使用mysql 資料庫。 1、創建crm資料庫 2、將參考資料中的sql腳本導入到資料庫中 ... ...
  • 2.SpringMVC介紹 2.1.SpringMVC是什麼 SpringMVC是Spring組織下的一個表現層框架。和Struts2一樣。它是Spring框架組織下的一部分。我們可以從Spring的整體結構中看得出來: 2.2.SpringMVC的作用 1.接收Web請求中的參數 2.把處理好的數... ...
  • 場景 SpringCloud學習之運行第一個Eureka程式: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/90611451 SpringCloud -創建統一的依賴管理: https://blog.csdn.net/BADAO ...
  • 場景 Spring Cloud 為開發者提供了在分散式系統(配置管理,服務發現,熔斷,路由,微代理,控制匯流排,一次性 Token,全居瑣,Leader 選舉,分散式 Session,集群狀態)中快速構建的工具,使用 Spring Cloud 的開發者可以快速的啟動服務或構建應用、同時能夠快速和雲平臺 ...
  • "洛谷題目頁面傳送門" & "CodeForces題目頁面傳送門" 給定一棵樹$T=(V,E),|V|=2^n 2,|E|=2^n 3$,輸出所有的$x$,使得存在一棵滿二叉樹$T'$,將$T'$中節點$x$的一個兒子刪除並把這個兒子的所有兒子接到$x$下後等於$T$。升序輸出。 $n\le17$。 ...
  • 預設下載安裝完的vscode並不能準確提示和檢測PHP的語法錯誤,需要手動指定一下本機的PHP程式路徑。按下麵的操作配置完後就能在文件保存的時候檢測語法有無錯誤。打開文件->首選項->setting,把PHP的執行路徑填進去,前提是本機已經安裝了PHP程式{ "workbench.sideBar.l ...
  • "洛谷題目頁面傳送門" & "CodeForces題目頁面傳送門" 給定一個$n$個單詞的文本,第$i$個單詞的長度為$len_i$,要求截取文本的一段(單詞必須取整的),分若幹行放,同行詞語用空格分隔,使得每行的長度不超過$m$,最多放$s$行。求截取的單詞數最多的截法。 $n\in[1,10^6 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...