Spring Bean作用域與生命周期深入講解
1.作用域定義
限定程序中變量的可用范圍叫做作用域,或者說在源代碼中定義變量的某個區域就叫做作用域。
Bean 的作用域
而 Bean 的作用域是指 Bean 在 Spring 整個框架中的某種行為模式,比如 singleton 單例作用域,就表示 Bean 在整個 Spring 中隻有一份,它是全局共享的,那麼當其他人修改瞭這個值之後,那麼另一個人讀取到的就是被修改的值。
Bean 的 6 種作用域
Spring 容器在初始化一個 Bean 的實例時,同時會指定該實例的作用域。Spring有 6 種作用域,最後四種是基於 Spring MVC 生效的:
- singleton:單例作用域(默認作用域)
- prototype:原型作用域(多例作用域)
- request:請求作用域
- session:回話作用域
- application:全局作用域
- websocket:HTTP WebSocket 作用域
註意後 4 種狀態是 Spring MVC 中的值,在普通的 Spring 項目中隻有前兩種。
1,2為Spring普通項目(Spring Core) 3,4,5為Spring MVC 6屬於Spring WebSocket
singleton
- 官方說明:(Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
- 描述:該作用域下的Bean在IoC容器中隻存在一個實例:獲取Bean(即通過applicationContext.getBean等方法獲取)及裝配Bean(即通過@Autowired註入)都是同一個對象。
- 場景:通常無狀態的Bean使用該作用域。無狀態表示Bean對象的屬性狀態不需要更新
- 備註:Spring默認選擇該作用域
prototype
- 官方說明:Scopes a single bean definition to any number of object instances.
- 描述:每次對該作用域下的Bean的請求都會創建新的實例:獲取Bean(即通過applicationContext.getBean等方法獲取)及裝配Bean(即通過@Autowired註入)都是新的對象實例。
- 場景:通常有狀態的Bean使用該作用域
request
- 官方說明:Scopes a single bean definition to the lifecycle of a single HTTP request. Thatis, each HTTP request has its own instance of a bean created off the back of a singlebean definition. Only valid in the context of a web-aware Spring ApplicationContext.
- 描述:每次http請求會創建新的Bean實例,類似於prototype
- 場景:一次http的請求和響應的共享Bean
- 備註:限定SpringMVC中使用
session
- 官方 說明:Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
- 描述:在一個http session中,定義一個Bean實例
- 場景: 用戶回話的共享Bean, 如:記錄 一個用戶的登陸信息
- 備註:限定SpringMVC中使用
application(瞭解)
- 官方說明:Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
- 描述:在一個http servlet Context中,定義一個Bean實例
- 場景:Web應 的上下 信息, 如:記錄一個應用的共享信息
- 備註:限定SpringMVC中使用
websocket(瞭解)
- 官方說明:Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.
- 描述:在一個HTTP WebSocket的 命周期中,定義一個Bean實例
- 場景:WebSocket的每次會話中,保存瞭一個Map結構的頭信息,將用來包裹客戶端消息頭。第一次初始化後,直到WebSocket結束都是同一個Bean。
- 備註:限定Spring WebSocket中使用
單例作用域(singleton)和全局作用域(application)區別
singleton 是 Spring Core 的作用域;
application 是 Spring Web 中的作用域;
singleton 作 於 IoC 的容器, application 作 於 Servlet 容器。
2.設置作用域
使用@Scope
標簽就可以聲明Bean的作用域,比如設置Bean的作用域
@Scope
標簽可以修飾方法,也可以修飾類,@Scope
有兩種設置方式:
1.直接設置值:@Scope("prototype")
2.直接枚舉設置:@Scope("ConfigurableBeanFactory.SCOPE_PROTOTYPE")
3.Bean 原理分析
3.1 Bean(Spring)執行流程
Bean 執行 流程(Spring 執 流程):啟動 Spring 容器 -> 實例化 Bean(分配內存空間,從 到有) -> Bean 註冊到 Spring 中(存操作) -> 將 Bean 裝配到需要的類中(取操作)。
3.2 Bean生命周期
所謂的生命周期指的是一個對象從誕生到銷毀的整個生命過程,我們把這個過程就叫做一個對象的生命周期。
Bean 的生命周期分為以下 5 部分:
實例化 Bean(為 Bean 分配內存空間)【實例化!=初始化;隻是執行分配內存空間的功能】
設置屬性(Bean 註入和裝配)【執行依賴類的註入A需要使用B的方法,先初始化並將B加載到當前類】
Bean 初始化
- 實現瞭各種Aware 通知的方法,如BeanNameAware、BeanFactoryAware、ApplicationContextAware 的接口方法;
- 執行BeanPostProcessor 初始化前置方法;
- 執行
@PostConstruct
初始化方法,依賴註入操作之後被執行; - 執行指定的 init-method方法(如果有指定的話);
- 執行BeanPostProcessor 初始化後置方法。
使用Bean
銷毀 Bean
銷毀容器的各種 法,如 @PreDestroy、DisposableBean 接口方法、destroy-method。
執行流程如下圖所示:
實例化和初始化的區別
實例化和屬性設置是 Java 級別的系統“事件”,其操作過程不可人工幹預和修改;而初始化是給開發者提供的,可以在實例化之後,類加載完成之前進行自定義“事件”處理。
生命流程的“故事”
Bean 的生命流程看似繁瑣,但咱們可以以生活中的場景來理解它,比如我們現在需要買一棟房子,那麼我們的流程是這樣的:
- 先買房(實例化,從無到有);
- 裝修(設置屬性);
- 買傢電,如洗衣機、冰箱、電視、空調等([各種]初始化);
- 入住(使用 Bean);
- 賣出去(Bean 銷毀)。
生命周期演示:
package com.beans; import org.springframework.beans.factory.BeanNameAware; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; public class BeanLifeComponent implements BeanNameAware { @PostConstruct public void postConstruct() { System.out.println("執行 PostConstruct()"); } public void init() { System.out.println("執行 BeanLifeComponent init-method"); } public void destory() { System.out.println("執行瞭 destory 方法"); } @PreDestroy public void preDestroy() { System.out.println("執行:preDestroy()"); } public void setBeanName(String s) { System.out.println("執行瞭 setBeanName 方法:" + s); } }
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" xmlns:content="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 設置需要存儲到 spring 中的 bean 根目錄 --> <content:component-scan base-package="com.beans"></content:component-scan> <bean id="beanlife" class="com.beans.BeanLifeComponent" init-method="init" destroy-method="destory"></bean> </beans>
調用類:
package com; import com.beans.BeanLifeComponent; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App2 { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); BeanLifeComponent beanLifeComponent = context.getBean(BeanLifeComponent.class); System.out.println("執行銷毀方法"); beanLifeComponent.destory(); // 執行銷毀方法 } }
步驟 2 和步驟 3 的順序不能打個顛倒!!!
到此這篇關於Spring Bean作用域與生命周期深入講解的文章就介紹到這瞭,更多相關Spring Bean作用域與生命周期內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!