Spring中Bean的作用域、實例化方式、生命周期、循環依賴問題

Spring中Bean的作用域、實例化方式、生命周期、循環依賴問題

  • 一、Bean的作用域
    • 1.singleton
    • 2.prototype
    • 3.其他scope值
  • 二、Bean的實例化方式
    • 1.通過構造方法實例化
    • 2.通過簡單工廠模式實例化
    • 3.通過factory-bean實例化
    • 4.通過FactoryBean接口實例化
    • 5.BeanFactory和FactoryBean的區別
      • (1)BeanFactory
      • (2)FactoryBean
  • 三、Bean的生命周期
    • 1.什么是Bean的生命周期
    • 2.為什么要知道Bean的生命周期
    • 3.Bean的生命周期之5步
    • 4.Bean生命周期之7步
    • 5.Bean生命周期之10步
    • 6.Bean的作用域不同,管理方式不同
    • 7.自己new的對象如何讓Spring管理
  • 四、Bean的循環依賴問題
    • 1.什么是Bean的循環依賴
    • 2.singleton下的set注入產生的循環依賴
    • 3. prototype下的set注入產生的循環依賴
    • 4.singleton下的構造注入產生的循環依賴
    • 5.Spring解決循環依賴的機理


一、Bean的作用域

1.singleton

  • 默認情況下,Spring的IoC容器創建的Bean對象是單例的。
  • 默認情況下,Bean對象的創建是在初始化Spring上下文的時候就完成了。

2.prototype

  • 如果想讓Spring的Bean對象以多例的形式存在,可以在bean標簽中指定scope屬性的值為:prototype,這樣Spring會在每一次執行getBean()方法的時候創建Bean對象,調用幾次則創建幾次。
<?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 id="sb" class="com.gdb.spring6.beans.SpringBean" scope="prototype" />
</beans>

3.其他scope值

  • scope屬性的值不止兩個,它一共包括8個選項:
    • singleton:默認的,單例。
    • prototype:原型。每調用一次getBean()方法則獲取一個新的Bean對象。或每次注入的時候都是新對象。
    • request:一個請求對應一個Bean。僅限于在WEB應用中使用。
    • session:一個會話對應一個Bean。僅限于在WEB應用中使用。
    • global session:portlet應用中專用的。如果在Servlet的WEB應用中使用global session的話,和session一個效果。(portlet和servlet都是規范。servlet運行在servlet容器中,例如Tomcat。portlet運行在portlet容器中。)
    • application:一個應用對應一個Bean。僅限于在WEB應用中使用。
    • websocket:一個websocket生命周期對應一個Bean。僅限于在WEB應用中使用。
    • 自定義scope:很少使用。

二、Bean的實例化方式

  • Spring為Bean提供了多種實例化方式,通常包括4種方式。(也就是說在Spring中為Bean對象的創建準備了多種方案,目的是:更加靈活)

1.通過構造方法實例化

  • 參考我的博客====>Spring對IoC的是實現中的Spring的第一個程序。

2.通過簡單工廠模式實例化

  • 第一步:定義一個Bean
package com.gdb.spring6.bean;public class Vip {
}
  • 第二步:編寫簡單工廠模式當中的工廠類
package com.gdb.spring6.bean;public class VipFactory {public static Vip get(){return new Vip();}
}
  • 第三步:在Spring配置文件中指定創建該Bean的方法(使用factory-method屬性指定)
<bean id="vipBean" class="com.gdb.spring6.bean.VipFactory" factory-method="get"/>

3.通過factory-bean實例化

  • 這種方式本質上是:通過工廠方法模式進行實例化。
  • 第一步:定義一個Bean
package com.gdb.spring6.bean;public class Vip {
}
  • 第二步:定義具體工廠類,工廠類中定義實例方法
    • 在這里可以在創建Bean的前后進行加工處理。
package com.gdb.spring6.bean;public class VipFactory {public Vip get(){return new Vip();}
}
  • 第三步:在Spring配置文件中指定factory-bean以及factory-method
<bean id="vipFactory" class="com.gdb.spring6.bean.VipFactory"/>
<bean id="vipBean" factory-bean="vipFactory" factory-method="get"/>

4.通過FactoryBean接口實例化

  • 以上的第三種方式中,factory-bean是我們自定義的,factory-method也是我們自己定義的。
  • 在Spring中,當你編寫的類直接實現FactoryBean接口之后,factory-bean不需要指定了,factory-method也不需要指定了。
  • factory-bean會自動指向實現FactoryBean接口的類,factory-method會自動指向getObject()方法。
  • 第一步:定義一個Bean
package com.gdb.spring6.bean;public class Vip {
}
  • 第二步:編寫一個類實現FactoryBean接口
package com.gdb.spring6.bean;import org.springframework.beans.factory.FactoryBean;public class VipFactoryBean implements FactoryBean<Vip> {@Overridepublic Vip getObject() throws Exception {return new Vip ();}@Overridepublic Class<?> getObjectType() {return null;}@Overridepublic boolean isSingleton() {// true表示單例// false表示原型return true;}
}
  • 第三步:在Spring配置文件中配置FactoryBean
<bean id="vipBean" class="com.gdb.spring6.bean.VipFactoryBean"/>
  • FactoryBean在Spring中是一個接口。被稱為“工廠Bean”。“工廠Bean”是一種特殊的Bean。所有的“工廠Bean”都是用來協助Spring框架來創建其他Bean對象的。
  • 其實FactoryBean就是一個抽象工廠。
  • 通過FactoryBean這個工廠Bean主要是想對普通Bean進行加工處理。

5.BeanFactory和FactoryBean的區別

(1)BeanFactory

  • Spring IoC容器的頂級對象,BeanFactory被翻譯為“Bean工廠”,在Spring的IoC容器中,“Bean工廠”負責創建Bean對象。
  • BeanFactory是工廠。

(2)FactoryBean

  • FactoryBean:它是一個Bean,是一個能夠輔助Spring實例化其它Bean對象的一個Bean。
  • 在Spring中,Bean可以分為兩類:
    • 第一類:普通Bean
    • 第二類:工廠Bean(記住:工廠Bean也是一種Bean,只不過這種Bean比較特殊,它可以輔助Spring實例化其它Bean對象。)

三、Bean的生命周期

1.什么是Bean的生命周期

  • Spring其實就是一個管理Bean對象的工廠。它負責對象的創建,對象的銷毀等。
  • 所謂的生命周期就是:對象從創建開始到最終銷毀的整個過程。
  • 什么時候創建Bean對象?
  • 創建Bean對象的前后會調用什么方法?
  • Bean對象什么時候銷毀?
  • Bean對象的銷毀前后調用什么方法?

2.為什么要知道Bean的生命周期

  • 其實生命周期的本質是:在哪個時間節點上調用了哪個類的哪個方法。
  • 我們需要充分的了解在這個生命線上,都有哪些特殊的時間節點。
  • 只有我們知道了特殊的時間節點都在哪,到時我們才可以確定代碼寫到哪。
  • 我們可能需要在某個特殊的時間點上執行一段特定的代碼,這段代碼就可以放到這個節點上。當生命線走到這里的時候,自然會被調用。

3.Bean的生命周期之5步

  • Bean生命周期的管理,可以參考Spring的源碼:AbstractAutowireCapableBeanFactory類的doCreateBean()方法。
  • Bean生命周期可以粗略的劃分為五大步:
    • 第一步:實例化Bean
    • 第二步:Bean屬性賦值
    • 第三步:初始化Bean
    • 第四步:使用Bean
    • 第五步:銷毀Bean
  • 需要注意的:
    • 第一:只有正常關閉spring容器,bean的銷毀方法才會被調用。
    • 第二:ClassPathXmlApplicationContext類才有close()方法。
    • 第三:配置文件中的init-method指定初始化方法。destroy-method指定銷毀方法。(初始化和銷毀方法,需要自己在Bean中編寫,然后在配置文件中進行配置)

4.Bean生命周期之7步

  • 在以上的5步中,第3步是初始化Bean,如果你還想在初始化前和初始化后添加代碼,可以加入“Bean后處理器”。
  • 編寫一個類實現BeanPostProcessor類,并且重寫before和after方法:
package com.gdb.spring6.bean;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;public class LogBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("Bean后處理器的before方法執行,即將開始初始化");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("Bean后處理器的after方法執行,已完成初始化");return bean;}
}
  • 在spring.xml文件中配置“Bean后處理器”:
<!--配置Bean后處理器。這個后處理器將作用于當前配置文件中所有的bean。-->
<bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
  • 一定要注意:在spring.xml文件中配置的Bean后處理器將作用于當前配置文件中所有的Bean。

5.Bean生命周期之10步

在這里插入圖片描述

6.Bean的作用域不同,管理方式不同

  • Spring 根據Bean的作用域來選擇管理方式。
    • 對于singleton作用域的Bean,Spring 能夠精確地知道該Bean何時被創建,何時初始化完成,以及何時被銷毀;
    • 而對于 prototype 作用域的 Bean,Spring 只負責創建,當容器創建了 Bean 的實例后,Bean 的實例就交給客戶端代碼管理,Spring 容器將不再跟蹤其生命周期。
      * 對于 prototype 作用域Spring容器管理 Bean生命周期的前八步。

7.自己new的對象如何讓Spring管理

  • 有些時候可能會遇到這樣的需求,某個java對象是我們自己new的,然后我們希望這個對象被Spring容器管理,怎么實現?
package com.gdb.spring6.test;import com.gdb.spring6.bean.User;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;public class RegisterBeanTest {@Testpublic void testBeanRegister(){// 自己new的對象User user = new User();System.out.println(user);// 創建 默認可列表BeanFactory 對象DefaultListableBeanFactory factory = new DefaultListableBeanFactory();// 注冊Beanfactory.registerSingleton("userBean", user);// 從spring容器中獲取beanUser userBean = factory.getBean("userBean", User.class);System.out.println(userBean);}
}

四、Bean的循環依賴問題

1.什么是Bean的循環依賴

  • A對象中有B屬性。B對象中有A屬性。這就是循環依賴。我依賴你,你也依賴我。
    在這里插入圖片描述

2.singleton下的set注入產生的循環依賴

  • 在singleton + setter模式注入的情況下,循環依賴是沒有問題的。Spring可以解決這個問題。
    • 主要原因是:在這種模式下 Spring 對 Bean 的管理主要分為清晰的兩個階段:
      • 第一階段:在Spring容器加載的時候,實例化Bean,只要其中任意一個Bean實例化之后,馬上進行“曝光”【不等屬性賦值曝光】。
      • 第二階段:Bean“曝光”之后,再進行屬性的賦值(調用set方法。)
    • 核心解決方案是:實例化對象和對象的屬性賦值分為兩個階段來完成的。

3. prototype下的set注入產生的循環依賴

  • 當循環依賴的所有Bean的scope="prototype"的時候,產生的循環依賴,Spring是無法解決的,會出現BeanCurrentlyInCreationException異常。
  • 如果其中一個是singleton,另一個是prototype,是沒有問題的。

4.singleton下的構造注入產生的循環依賴

  • 因為構造方法注入會導致實例化對象的過程和對象屬性賦值的過程沒有分離開,必須在一起完成導致的。

5.Spring解決循環依賴的機理

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

  • 總結:
    • Spring只能解決setter方法注入的單例bean之間的循環依賴。ClassA依賴ClassB,ClassB又依賴ClassA,形成依賴閉環。Spring在創建ClassA對象后,不需要等給屬性賦值,直接將其曝光到bean緩存當中。在解析ClassA的屬性時,又發現依賴于ClassB,再次去獲取ClassB,當解析ClassB的屬性時,又發現需要ClassA的屬性,但此時的ClassA已經被提前曝光加入了正在創建的bean的緩存中,則無需創建新的的ClassA的實例,直接從緩存中獲取即可。從而解決循環依賴問題。

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

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

相關文章

【大廠AI課學習筆記NO.60】(13)模型泛化性的評價

我們學習了過擬合和欠擬合&#xff0c;具體見我的文章&#xff1a;https://giszz.blog.csdn.net/article/details/136440338 那么今天&#xff0c;我們來學習模型泛化性的評價。 泛化性的問題&#xff0c;我們也討論過了&#xff0c;那么如何評價模型的泛化性呢&#xff1f; …

激光SLAM技術助力富唯智能復合機器人的應用場景無限拓展

隨著科技的不斷進步&#xff0c;智能機器人已成為現代工業、服務、醫療等多個領域的重要角色。而在這一變革中&#xff0c;激光SLAM技術發揮著至關重要的作用。特別是對于富唯智能復合機器人來說&#xff0c;激光SLAM技術不僅提升了其智能化水平&#xff0c;更使其應用場景變得…

esp3455235

在這里插入代碼片gdasgdsfgdfh dfahahdfh

【促銷定價】背后的算法技術3-數據挖掘分析

【促銷定價】背后的算法技術3-數據挖掘分析 01 整體分析1&#xff09;整體概覽2&#xff09;類別型特征概覽3&#xff09;數值型特征概覽 02 聚合分析1&#xff09;天維度2&#xff09;品維度3&#xff09;價格維度4&#xff09;數量維度 03 相關分析1&#xff09;1級品類2&…

無公網ip環境使用DS file軟件遠程訪問內網群暉NAS中儲存的文件

文章目錄 1. 群暉安裝Cpolar2. 創建TCP公網地址3. 遠程訪問群暉文件4. 固定TCP公網地址5. 固定TCP地址連接 DS file 是一個由群暉公司開發的文件管理應用程序&#xff0c;主要用于瀏覽、訪問和管理存儲在群暉NAS&#xff08;網絡附加存儲&#xff09;中的文件。這個應用程序具有…

echarts如何實現3D餅圖(環形圖)?

一、實現的效果 二、具體步驟 1.安裝依賴 npm install echarts 2.引入echarts import * as echarts from echarts; 注意&#xff1a;這里需要用到echarts-gl&#xff0c;必須單獨引入才可以 import echarts-gl; 3.echarts部分代碼 我知道這部分內容很多&#xff0c;但只要cv…

社情民意調查的內容

本文由群狼調研&#xff08;長沙社情民意調查&#xff09;出品&#xff0c;歡迎轉載&#xff0c;請注明出處。社情民意調查的內容通常包括以下幾個方面&#xff1a; 1.社會熱點問題&#xff1a;針對當前社會熱點問題進行調查&#xff0c;收集公眾對該問題的態度和看法&#xf…

羊大師揭秘羊奶與健康,美味的保健佳品

羊大師揭秘羊奶與健康&#xff0c;美味的保健佳品 羊奶確實是一種美味且健康的保健佳品&#xff0c;其獨特的營養成分和風味使其成為許多人的健康選擇。以下是一些羊奶與健康的關系&#xff1a; 營養豐富&#xff1a;羊奶含有豐富的蛋白質、脂肪、礦物質和維生素&#xff0c;…

ruoyi-nbcio-plus的Vue3前端升級組件后出現的問題(一)

更多ruoyi-nbcio功能請看演示系統 gitee源代碼地址 前后端代碼&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a; http://122.227.135.243:9666 更多nbcio-boot功能請看演示系統 gitee源代碼地址 后端代碼&#xff1a; https://gitee.com/nbach…

大模型ChatGLM-6B實現本地部署

大模型ChatGLM-6B實現本地部署 一、寫在前面&#xff1a;二、ChatGLM-6B下載&#xff1a;三、項目所需要的環境配置&#xff1a;四、項目運行&#xff1a;五、遇到的主要問題及解決 一、寫在前面&#xff1a; 1、 確保你的電腦中已安裝git&#xff0c;git lfs。 2、確保你的電…

淺析前端的堆棧原理以及深淺拷貝原理

淺析前端的堆棧原理以及深淺拷貝原理 首先來看一個案例 const obj {name:hzw,age:18 } let objName2 obj objName2.age 12 console.log(obj,objName2) // {name: hzw, age: 12} {name: hzw, age: 12}這里是不是很奇怪&#xff0c;為什么&#xff0c;為什么我改變objName2的…

Hierarchical Text-ConditionalImage Generation with CLIP Latents筆記

1 Title Hierarchical Text-Conditional Image Generation with CLIP Latents&#xff08;Aditya Ramesh、Prafulla Dhariwal、Alex Nichol、Casey Chu、Mark Chen&#xff09; 2 Conclusion Contrastive models like CLIP have been shown to learn robust representations …

read()函數

read() 函數用于從文件描述符&#xff08;通常是套接字、文件等&#xff09;讀取數據。 #include <unistd.h>ssize_t read(int fd, void *buf, size_t count);fd&#xff1a; 是文件描述符&#xff0c;可以是套接字、文件等。 buf&#xff1a; 是一個指向要讀取數據的緩…

AirPods Pro 2 耳機推送新固件,蘋果Find My功能助力產品成長

蘋果公司面向 AirPods Pro 2&#xff08;包括 USB-C 和 Lightning 版本&#xff09;&#xff0c;推出了全新的測試版固件更新&#xff0c;版本號為 6E188&#xff0c;高于 12 月份發布的 6B34 固件。 蘋果和往常一樣&#xff0c;并沒有提供詳細的更新日志或者說明&#xff0c…

算法刷題day20:二分

目錄 引言概念一、借教室二、分巧克力三、管道四、技能升級五、冶煉金屬六、數的范圍七、最佳牛圍欄 引言 這幾天一直在做二分的題&#xff0c;都是上了難度的題目&#xff0c;本來以為自己的二分水平已經非常熟悉了&#xff0c;沒想到還是糊涂了一兩天才重新想清楚&#xff0…

力扣區間題:合并區間、插入區間

我們可以將區間按照左端點升序排列&#xff0c;然后遍歷區間進行合并操作。 我們先將第一個區間加入答案&#xff0c;然后依次考慮之后的每個區間&#xff1a; 如果答案數組中最后一個區間的右端點小于當前考慮區間的左端點&#xff0c;說明兩個區間不會重合&#xff0c;因此…

Java基于springboot的課程作業管理系統

摘 要 隨著科學技術的飛速發展&#xff0c;社會的方方面面、各行各業都在努力與現代的先進技術接軌&#xff0c;通過科技手段來提高自身的優勢&#xff0c;課程作業管理系統當然也不能排除在外。課程作業管理系統是以實際運用為開發背景&#xff0c;運用軟件工程原理和開發方法…

js跳出循環

只有for可以自己跳出循環 break可以退出多重循環&#xff0c;可以自行選擇退出哪一層 label: for (let i 0; i < arr.length; i) {if (arr[i].content) {break label}console.log(i) } label1: for (let i 0; i < arr.length; i) {label2: for (let j 0; j < arr.l…

Linux常見命令總結

1.創建文件夾 mkdir 目錄名 mkdir 文件夾名 創建單個文件夾 mkdir 文件夾1 文件夾2 文件夾3 創建多個文件夾 mkdir -p parent/child 創建多級文件夾 2.創建文件 touch 文件名 touch的主要功能有兩個,如果要創建的文件的名稱存在,將文件的創建時間修改到當前的系統時間(也…

五種常用的可視化項目管理工具

傳統的項目管理通常依賴于文本文檔&#xff0c;容易造成誤解和混亂。在快節奏的商業環境中&#xff0c;沒有哪個項目經理愿意處理繁重的文檔流程。 另一方面&#xff0c;可視化項目管理通常使用圖表和視覺板來展示復雜的項目信息。因此&#xff0c;項目經理能快速了解關鍵信息…