Spring Framework中的Bean生命周期

目錄

一.Bean生命周期的簡介

1.基本概念

2.Spring生命周期的幾大階段

3.注意點及小結

?4.生活案例

5.Spring容器管理JavaBean的初始化過程

二. Bean的單例選擇與多例選擇

1.單例選擇與多例選擇的優缺點

1.1單例模式的優點:

1.2單例模式的缺點:

1.3多例模式的優點:

1.4多例模式的缺點:

1.5 小結

2.案例演示單例模式與多例模式

1.演示在單例模式和多例模式下資源變量是否被污染

2. 判斷單例模式和多例模式的初始化

3.單例模式和多例模式的適用場景


一.Bean生命周期的簡介

1.基本概念

Bean生命周期指的是Bean在容器中創建、初始化、使用和銷毀的過程。Spring的IoC容器負責管理Bean的生命周期,確保它們按照預期的方式被創建和銷毀

2.Spring生命周期的幾大階段

  1. 實例化:在容器啟動時,Spring根據配置文件或注解等方式創建Bean的實例。這個階段是通過調用Bean的構造函數完成的。

  2. 屬性注入:在實例化后,Spring會通過各種方式(例如XML配置、注解、Java代碼等)將Bean所需的屬性值注入到Bean中。可以使用@Autowired@Value等注解來實現依賴注入。

  3. 初始化回調方法:在Bean的所有屬性被注入之后,Spring會調用Bean的初始化回調方法。常見的初始化回調方法是實現InitializingBean接口的afterPropertiesSet方法或使用@PostConstruct注解。

  4. 自定義初始化方法:除了使用初始化回調接口和注解外,開發人員還可以在Bean中定義自己的初始化方法。可以通過在Bean的方法上使用@Bean(initMethod = "customInit")注解來指定自定義的初始化方法。

  5. 使用Bean:在初始化后,Bean可以被容器和其他Bean使用。可以在其他Bean中使用依賴注入來獲取到已經初始化的Bean。

  6. 銷毀回調方法:當容器關閉時或者通過編程方式銷毀Bean時,Spring會調用Bean的銷毀回調方法。常見的銷毀回調方法是實現DisposableBean接口的destroy方法或使用@PreDestroy注解。

  7. 自定義銷毀方法:類似于初始化方法,開發人員可以在Bean中定義自己的銷毀方法。可以通過在Bean的方法上使用@Bean(destroyMethod = "customDestroy")注解來指定自定義的銷毀方法。

3.注意點及小結

當使用Java配置(如@Configuration)時,Bean的生命周期管理通常使用方法級別的@Bean注解,而不是XML配置中的<bean>元素。

總結起來,Spring Bean的生命周期包括實例化、屬性注入、初始化回調方法、自定義初始化方法、使用Bean、銷毀回調方法和自定義銷毀方法。Spring提供了多種方式來管理Bean的生命周期,開發人員可以根據需要選擇適合自己的方式

?4.生活案例

假設我們以一個人的生命周期作為生活實例來比喻Spring Bean的生命周期。

  1. 實例化:當一個人出生時,就相當于Bean在容器中被實例化的過程。一個新生嬰兒就是一個新的實例,具有獨立的身份。

  2. 屬性注入:隨著時間的推移,這個人會經歷各種學習和成長的過程,就像Bean在屬性注入階段接收到不同的屬性值。例如,這個人會接受教育、學習技能、掌握知識,這些都是人生中注入的屬性。

  3. 初始化回調方法:當這個人成年后,可能會選擇一個職業或自己的事業,就像Bean在初始化回調方法階段定義自己的職責和目標。這個人會明確自己的使命,并準備好開始工作。

  4. 自定義初始化方法:在人生的旅程中,這個人會發展自己的興趣愛好、價值觀和生活方式,就像Bean可以定義自己的初始化方法。這些方法可以幫助這個人構建自己的身份,并適應不同的環境。

  5. 使用:完成初始化后,這個人會活躍在社會中,與其他人交流、工作、合作,就像Bean在容器中被其他組件或應用程序使用。

  6. 銷毀回調方法:當一個人的生命接近尾聲或者出現一些變故時,他們開始為離開做準備。就像Bean的銷毀回調方法一樣,這個人可能會處理他們的后事,與親人和朋友告別,做好最后的安排。

  7. 自定義銷毀方法:在離開之前,這個人可以進行一些必要的準備,如寫遺囑、處理財務等,就像Bean可以定義自己的銷毀方法來處理必要的清理工作。

通過這個比喻,我們可以將Spring Bean的生命周期與一個人的生命周期進行對比,從而更好地理解Bean在容器中的創建、初始化、使用和銷毀的過程。

?

?Bean的生命周期就像我們的一生,人的終點是死亡,Bean的生命周期也一樣,終點都是一樣的,重要的是過程,所以這里也希望大家能夠熱愛生活

5.Spring容器管理JavaBean的初始化過程

1.xml/annotation/configuation 配置Javabean

2.BeanDefinitionReader解析配置的JavaBean得到BeanDefinition,最終得到List<BeanDefinition>集合

3.觸發BeanFactoryPostProcessor,在Javabean初始化之前執行自己的業務

4.spring中beanFactory,會通過List<BeanDefinition>集合遍歷初始化所有的Javabean對象

5.如果自己的JavaBean需要調動Spring上下文中的資源,那么需要實現*aware感知接口

6.如果自己的JavaBean已經初始化好了,還需擴展功能,那么需要借助BeanPostProcessor來實現

二. Bean的單例選擇與多例選擇

默認狀態下Bean的配置的單例的,當然,也可以選擇去配置多例的

1.單例選擇與多例選擇的優缺點

1.1單例模式的優點:

  1. 資源利用:單例模式在應用程序啟動時創建一個實例,并一直重用該實例,減少了對象創建和銷毀的開銷,可以有效利用系統資源。
  2. 全局性:單例模式可以在整個應用程序中共享數據,確保數據的一致性和可靠性。
  3. 狀態共享:由于單例只有一個實例,可以方便地在不同的組件之間共享狀態,簡化了組件之間的通信和數據傳遞。
  4. 線程安全:單例模式天生具有線程安全的特性,因為只有一個實例在操作,避免了并發訪問的問題。

1.2單例模式的缺點:

  1. 資源持有:單例模式的實例會一直存在于內存中,占用一定的系統資源,在某些情況下可能會導致資源浪費。
  2. 生命周期管理:單例模式的實例生命周期長,無法自動釋放資源,需要手動管理對象狀態和清理資源。
  3. 難以模擬測試:由于單例模式的全局性和狀態共享的特性,對于單元測試和模擬測試來說可能會更加困難,因為需要考慮到全局狀態的影響。

1.3多例模式的優點:

  1. 靈活性:多例模式可以根據需要創建多個實例,每個實例之間相互獨立并具有自己的狀態,可以更靈活地應對不同的需求。
  2. 隔離性:多例模式的實例相互獨立,不共享狀態,可以避免狀態污染和互相干擾的問題。
  3. 生命周期管理:每個多例實例的生命周期由Spring容器管理,可以自動釋放資源,減少內存泄漏的風險。
  4. 更易于測試:多例模式的實例相互獨立,可以更容易地進行單元測試和模擬測試,測試之間不會相互影響。

1.4多例模式的缺點:

  1. 資源占用:多例模式創建了多個實例,會占用更多的內存和系統資源。
  2. 對象管理復雜:多個實例需要由開發者自己管理和控制,需要注意實例的創建、銷毀和狀態管理,增加了設計和開發的復雜性。
  3. 線程安全:多例模式的實例在并發環境下需要額外考慮線程安全的問題,確保實例之間的數據不會沖突。

1.5 小結

單例模式適用于需要全局共享和狀態共享的情況,能夠提高資源利用和數據一致性,但需要注意資源管理和生命周期的維護。而多例模式適用于需要靈活性和隔離性的情況,能夠減少資源占用和相互影響,但需要開發者自行管理和控制實例的創建和狀態。選擇單例還是多例取決于具體的業務需求和系統設計的考慮。

2.案例演示單例模式與多例模式

1.演示在單例模式和多例模式下資源變量是否被污染

1.準備好資源

package com.YU.beanlife;import java.util.List;import com.YU.ioc.service.UserService;
import com.YU.ioc.service.impl.UserServiceImpl1;
import com.YU.ioc.service.impl.UserServiceImpl2;public class ParamAction {private int age;private String name;private List<String> hobby;private int num = 1;// private UserBiz userBiz = new UserBizImpl1();public ParamAction() {super();}public ParamAction(int age, String name, List<String> hobby) {super();this.age = age;this.name = name;this.hobby = hobby;}public void execute() {// userBiz.upload();// userBiz = new UserBizImpl2();System.out.println("this.num=" + this.num++);System.out.println(this.name);System.out.println(this.age);System.out.println(this.hobby);}
}

2.準備好Bean工廠

package com.YU.beanlife;public class InstanceFactory {public void init() {System.out.println("初始化方法");}public void destroy() {System.out.println("銷毀方法");}public void service() {System.out.println("業務方法");}
}

3.配置xml中的bean目錄

<!--spring的生命周期--><bean class="com.YU.beanlife.ParamAction" id="paramAction"><constructor-arg name="name" value="死仔"></constructor-arg><constructor-arg name="age" value="21"></constructor-arg><constructor-arg name="hobby"><list><value>抽煙</value><value>打go</value><value>燙頭</value></list></constructor-arg></bean><bean id="instanceFactory" class="com.YU.beanlife.InstanceFactory"scope="prototype" init-method="init" destroy-method="destroy"></bean>

4.編寫測試程序

package com.YU.beanlife;import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;/** spring	bean的生命週期* spring	bean的單例多例*/
public class Demo2 {// 體現單例與多例的區別@Testpublic void test1() {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
//		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");// System.out.println(p1==p2);p1.execute();p2.execute();//		單例時,容器銷毀instanceFactory對象也銷毀;多例時,容器銷毀對象不一定銷毀;applicationContext.close();}// 體現單例與多例的初始化的時間點 instanceFactory@Testpublic void test2() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");InstanceFactory instanceFactory = (InstanceFactory) applicationContext.getBean("instanceFactory");}// BeanFactory會初始化bean對象,但會根據不同的實現子類采取不同的初始化方式// 默認情況下bean的初始化,單例模式立馬會執行,但是此時XmlBeanFactory作為子類,單例模式下容器創建,bean依賴沒有初始化,只有要獲取使用bean對象才進行初始化@Testpublic void test3() {// ClassPathXmlApplicationContext applicationContext = new// ClassPathXmlApplicationContext("/spring-context.xml");Resource resource = new ClassPathResource("/spring-context.xml");BeanFactory beanFactory = new XmlBeanFactory(resource);
//		InstanceFactory i1 = (InstanceFactory) beanFactory.getBean("instanceFactory");}}

其中Test1測試結果為:

由于我們默認使用的是單例模式,所以在運行時出現了變量污染,num值變為2?

當我們配置多例模式同樣運行Test1時

scope="prototype"

?運行結果:

由此可得知我們的變量沒有被污染?

2. 判斷單例模式和多例模式的初始化

配置和上面是一樣的

1.當我們運行Test2時測試JavaBean是否跟著初始化

單例模式運行結果:

由單例模式可以看出發生了初始化?

多例模式運行結果:

由此得知并沒有出現初始化

當我們用多例模式運行Test3時

運行結果:

?看到紅框中的代碼,當我們的JavaBean時才會初始化

小結:

由三次運行結果我們可以得出:

1.單例模式中的JavaBean是跟著Spring上下文初始化的,容器生成對象跟著生成,容器死亡,對象死亡

2.多例模式走的Javabean是使用時才會創建,銷毀要跟著Jvm走

3.單例模式和多例模式的適用場景

單例模式和多例模式在不同的場景下具有不同的適用性。以下是它們常見的適用場景:

適用于單例模式的場景:

  1. 資源共享:當需要在應用程序的多個組件之間共享同一份資源或數據時,單例模式可以確保全局范圍內的數據一致性。
  2. 工廠類:當需要創建一個全局工廠類來統一管理對象的創建和生命周期時,單例模式可以確保該工廠類始終只有一個實例。
  3. 配置信息:當需要在應用程序中加載一份全局的配置信息,并且多個組件需要共享該配置信息時,單例模式可以確保配置信息的一致性和高效訪問。
  4. 日志記錄器:當需要在整個應用程序中使用同一個日志記錄器來記錄日志時,單例模式可以確保日志的一致性和集中管理。

適用于多例模式的場景:

  1. 并發請求處理:當需要在多線程或并發環境下處理請求,并且每個請求使用獨立的實例來保證狀態隔離時,多例模式可以為每個請求創建一個獨立的對象。
  2. 對象池:當需要管理一組可復用的對象,并且對象在不同的時刻需要創建和銷毀時,多例模式可以提供對象池來管理對象的生命周期,以減少創建和銷毀的開銷。
  3. 狀態管理:當對象的狀態需要在不同的上下文環境中獨立維護和處理時,多例模式可以為每個上下文環境創建一個獨立的實例,以避免狀態沖突和相互干擾。
  4. 服務提供者:當系統需要支持多個相同類型的服務提供者,并且每個服務提供者需要獨立的實例時,多例模式可以滿足服務提供者的創建和管理需求。

注意!!!

單例模式在一些場景下可能存在共享資源競爭、線程安全等問題,需要謹慎設計和考慮并發訪問的情況。多例模式在一些場景下可能會增加資源消耗和對象管理的復雜性,需要權衡資源利用和代碼復雜度之間的平衡。在實際應用中,根據具體的業務需求和系統設計要求來選擇單例模式或多例模式。

?

?很感謝各位大佬的觀看,點個關注不迷路,大家的點贊和收藏是博主最大的創作動力,謝謝啦

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/43088.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/43088.shtml
英文地址,請注明出處:http://en.pswp.cn/news/43088.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JDK 8 升級 JDK 17 全流程教學指南

JDK 8 升級 JDK 17 首先已有項目升級是會經歷一個較長的調試和自測過程來保證允許和兼容沒有問題。先說幾個重要的點 遇到問題別放棄仔細閱讀報錯&#xff0c;精確到每個單詞每一行&#xff0c;不是自己項目的代碼也要點進去看看源碼到底是為啥報錯明確你項目引入的包&#x…

第三屆“贛政杯”網絡安全大賽 | 賽寧筑牢安全應急防線

??為持續強化江西省黨政機關網絡安全風險防范意識&#xff0c;提高信息化崗位從業人員基礎技能&#xff0c;提升應對網絡安全風險處置能力。由江西省委網信辦、江西省發展改革委主辦&#xff0c;江西省大數據中心、國家計算機網絡與信息安全管理中心江西分中心承辦&#xff0…

Qt掃盲-QTableView理論總結

QTableView理論總結 一、概述二、導航三、視覺外觀四、坐標系統五、示例代碼1. 性別代理2. 學生信息模型3. 對應視圖 一、概述 QTableView實現了一個tableview 來顯示model 中的元素。這個類用于提供之前由QTable類提供的標準表&#xff0c;但這個是使用Qt的model/view架構提供…

MySQL 存儲過程

create procedure 存儲過程名 &#xff08;in | out | INPUT 參數名 參數類型&#xff0c;。。。&#xff09; 【characteristics 。。。】begin存儲過程體end存儲過程的參數類型 IN 、OUT、INPUT 都可以在一個存儲過程帶多個 沒有參數&#xff08;無參數無返回&#xff09;僅…

ProGuard + SpringBoot3 + JDK17

1、pom依賴 <?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.…

android平臺的語音聊天助手源碼

目錄 1 android平臺的語音聊天助手源碼 1.1 Setting 1.1.1 onChildClick 1.1.2 if (groupPosition == 0) {// 語音識別設置 android平臺的語音聊天助手源碼 Setting onChildClick

神經網絡基礎-神經網絡補充概念-11-向量化邏輯回歸

概念 通過使用 NumPy 數組來進行矩陣運算&#xff0c;將循環操作向量化。 向量化的好處在于它可以同時處理多個樣本&#xff0c;從而加速計算過程。在實際應用中&#xff0c;尤其是處理大規模數據集時&#xff0c;向量化可以顯著提高代碼的效率。 代碼實現-以邏輯回歸為例 i…

邊緣網絡的作用及管理工具

自從引入軟件即服務 &#xff08;SaaS&#xff09; 以來&#xff0c;它一直引領著全球按需軟件部署創新的競賽&#xff0c;它提供的靈活性以及其云計算架構帶來的易于集成使其成為交付業務應用程序的標準。 在 SaaS 模型中&#xff0c;最佳用戶體驗的三重奏涉及無縫設置、低延…

JMeter 特殊組件-邏輯控制器與BeanShell PreProcessor 使用示例

文章目錄 前言JMeter 特殊組件-邏輯控制器與BeanShell PreProcessor 使用示例1. 邏輯控制器使用1.1. While Controller 使用示例1.2. 如果&#xff08;If&#xff09;控制器 使用示例 2. BeanShell PreProcessor 使用示例 前言 如果您覺得有用的話&#xff0c;記得給博主點個贊…

Java課題筆記~ SpringBoot簡介

1. 入門案例 問題導入 SpringMVC的HelloWord程序大家還記得嗎&#xff1f; SpringBoot是由Pivotal團隊提供的全新框架&#xff0c;其設計目的是用來簡化Spring應用的初始搭建以及開發過程 原生開發SpringMVC程序過程 1.1 入門案例開發步驟 ①&#xff1a;創建新模塊&#…

設計模式-過濾器模式(使用案例)

過濾器模式&#xff08;Filter Pattern&#xff09;或標準模式&#xff08;Criteria Pattern&#xff09;是一種設計模式&#xff0c;這種模式允許開發人員使用不同的標準來過濾一組對象&#xff0c;通過邏輯運算以解耦的方式把它們連接起來。這種類型的設計模式屬于結構型模式…

服務器安裝centos7踩坑

1、制作啟動工具 下載iso https://developer.aliyun.com/mirror/?spma2c6h.25603864.0.0.20387abbo2RFbn http://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/?spma2c6h.25603864.0.0.1995f5ad4AhJaW下載 UltraISO https://cn.ultraiso.net/插入u盤啟動 到了如圖所示頁面…

nginx php-fpm安裝配置

nginx php-fpm安裝配置 nginx本身不能處理PHP&#xff0c;它只是個web服務器&#xff0c;當接收到請求后&#xff0c;如果是php請求&#xff0c;則發給php解釋器處理&#xff0c;并把結果返回給客戶端。 nginx一般是把請求發fastcgi管理進程處理&#xff0c;fascgi管理進程選…

架構演進及常用架構

1架構演進及常用架構 1.1單體分層架構 1.2 多應用微服務架構 1.3 分布式集群部署 部署 CDN 節點&#xff1a; 用戶訪問量的增加意味著用戶地域的分散請求&#xff0c;如果所有請求都直接發送中心服務器的話&#xff0c;距離越遠&#xff0c;響應速度越差&#xff0c;這時就需…

【編織時空四:探究順序表與鏈表的數據之旅】

本章重點 鏈表的分類 帶頭雙向循環鏈表接口實現 順序表和鏈表的區別 緩存利用率參考存儲體系結構 以及 局部原理性。 一、鏈表的分類 實際中鏈表的結構非常多樣&#xff0c;以下情況組合起來就有8種鏈表結構&#xff1a; 1. 單向或者雙向 2. 帶頭或者不帶頭 3. 循環或者非…

yolov5封裝進ros系統

一&#xff0c;要具備ROS環境 ROS環境搭建可以參考我之前的文章 ROS參考文章1 ROS參考文章2 ? 建立ROS工作空間 ROS系統由自己的編譯空間規則。 cd 你自己想要的文件夾&#xff08;我一般是home目錄&#xff09; mkdir -p (你自己的文件夾名字&#xff0c;比如我是yolov5…

C++的stack和queue+優先隊列

文章目錄 什么是容器適配器底層邏輯為什么選擇deque作為stack和queue的底層默認容器優先隊列優先隊列的模擬實現stack和queue的模擬實現 什么是容器適配器 適配器是一種設計模式(設計模式是一套被反復使用的、多數人知曉的、經過分類編目的、代碼設計經驗的總 結)&#xff0c;…

Greenplum多級分區表添加分區報錯ERROR: no partitions specified at depth 2

一般來說&#xff0c;我們二級分區表都會使用模版&#xff0c;如果沒有使用模版特性&#xff0c;那么就會報ERROR: no partitions specified at depth 2類似的錯誤。因為沒有模版&#xff0c;必須要顯式指定分區。 當然我們在建表的時候&#xff0c;如果沒有指定&#xff0c;那…

PyTorch訓練深度卷積生成對抗網絡DCGAN

文章目錄 DCGAN介紹代碼結果參考 DCGAN介紹 將CNN和GAN結合起來&#xff0c;把監督學習和無監督學習結合起來。具體解釋可以參見 深度卷積對抗生成網絡(DCGAN) DCGAN的生成器結構&#xff1a; 圖片來源&#xff1a;https://arxiv.org/abs/1511.06434 代碼 model.py impor…

VSCode 使用總結

快捷鍵 在 Visual Studio Code (VSCode) 中&#xff0c;有許多常用的快捷鍵可以提高編程效率。以下是一些常見的 VSCode 編程項目快捷鍵&#xff1a; 編輯器操作&#xff1a; 撤銷&#xff1a;Ctrl Z重做&#xff1a;Ctrl Shift Z復制&#xff1a;Ctrl C剪切&#xff1a;C…