1. 程式人生 > >Spring之Bean的作用域與生命週期

Spring之Bean的作用域與生命週期

在前面部落格中提到容器啟動獲得BeanDefinition物件中有一個scope 屬性。該屬性控制著bean物件的作用域。本章節介紹Bean的作用域及生命週期,瞭解bean是怎麼來的又怎麼沒的。

一、Bean的作用域
在Bean容器啟動會讀取bean的xml配置檔案,然後將xml中每個bean元素分別轉換成BeanDefinition物件。在BeanDefinition物件中有scope 屬性,就是它控制著bean的作用域。
Spring框架支援5種作用域,有三種作用域是當開發者使用基於web的ApplicationContext的時候才生效的。下面就是Spring直接支援的作用域了,當然開發者也可以自己定製作用域。

作用域

描述

單例(singleton)

(預設)每一個Spring IoC容器都擁有唯一的一個例項物件

原型(prototype

一個Bean定義,任意多個物件

請求(request

一個HTTP請求會產生一個Bean物件,也就是說,每一個HTTP請求都有自己的Bean例項。只在基於webSpring ApplicationContext中可用

會話(session

限定一個Bean的作用域為HTTPsession的生命週期。同樣,只有基於

webSpring ApplicationContext才能使用

全域性會話(global session

限定一個Bean的作用域為全域性HTTPSession的生命週期。通常用於入口網站場景,同樣,只有基於webSpring ApplicationContext可用

我們可以以XMLInstance類為基礎演示一下singleton和prototype作用域。
這裡使用通過BeanFactory的getBean方法獲取兩次bean物件。

        XMLInstance instance=(XMLInstance)factory.getBean("xmlinstance");
        instance.setName(
"123"); instance.Breath(); instance=(XMLInstance)factory.getBean("xmlinstance"); instance.Breath();

如果我們採用bean預設的作用域singleton,如下配置,則兩個getbean獲取的物件是一致的。

  <bean id="xmlinstance" class="com.demo.model.XMLInstance" scope="singleton">
      <property name="air" ref="CleanAir"></property>
      <property name="name" value="abc"></property>
  </bean>
輸出結果:
Name:123;Air:CleanAir
Name:123;Air:CleanAir

如果我們採用bean預設的作用域prototype,如下配置,則兩個getbean獲取的物件是不一致的。

  <bean id="xmlinstance" class="com.demo.model.XMLInstance" scope="prototype">
      <property name="air" ref="CleanAir"></property>
      <property name="name" value="abc"></property>
  </bean>
輸出結果:
Name:123;Air:CleanAir
Name:abc;Air:CleanAir

二、Bean的生命週期
前面章節介紹了bean容器以及bean的配置與注入,本章節學習bean的生命週期,瞭解bean是怎麼來的又是怎麼沒的。

ApplicationContext容器中,Bean的生命週期流程如上圖所示,流程大致如下:
1.首先容器啟動後,會對scope為singleton且非懶載入的bean進行例項化,
2.按照Bean定義資訊配置資訊,注入所有的屬性,
3.如果Bean實現了BeanNameAware介面,會回撥該介面的setBeanName()方法,傳入該Bean的id,此時該Bean就獲得了自己在配置檔案中的id,
4.如果Bean實現了BeanFactoryAware介面,會回撥該介面的setBeanFactory()方法,傳入該Bean的BeanFactory,這樣該Bean就獲得了自己所在的BeanFactory,
5.如果Bean實現了ApplicationContextAware介面,會回撥該介面的setApplicationContext()方法,傳入該Bean的ApplicationContext,這樣該Bean就獲得了自己所在的ApplicationContext,
6.如果有Bean實現了BeanPostProcessor介面,則會回撥該介面的postProcessBeforeInitialzation()方法,
7.如果Bean實現了InitializingBean介面,則會回撥該介面的afterPropertiesSet()方法,
8.如果Bean配置了init-method方法,則會執行init-method配置的方法,
9.如果有Bean實現了BeanPostProcessor介面,則會回撥該介面的postProcessAfterInitialization()方法,
10.經過流程9之後,就可以正式使用該Bean了,對於scope為singleton的Bean,Spring的ioc容器中會快取一份該bean的例項,而對於scope為prototype的Bean,每次被呼叫都會new一個新的物件,期生命週期就交給呼叫方管理了,不再是Spring容器進行管理了
11.容器關閉後,如果Bean實現了DisposableBean介面,則會回撥該介面的destroy()方法,
12.如果Bean配置了destroy-method方法,則會執行destroy-method配置的方法,至此,整個Bean的生命週期結束。 這裡在UserBean類基礎上進行改造,增加了name屬性並實現了ApplicationContextAware介面。
package com.demo.model;

import org.springframework.beans.BeansException;
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;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

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

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("set方法被呼叫");
    }

    public UserBean() {
         System.out.println("UserBean類構造方法");
    }
    
    public void setBeanName(String name) {
        System.out.println("BeanNameAware被呼叫");
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware被呼叫");    
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean被呼叫");    
    }

    public void destroy() throws Exception {
        System.out.println("DisposableBean被呼叫");
    }
    //自定義的初始化函式 
    public void myInit() { 
        System.out.println("myInit被呼叫");
    } 
    //自定義的銷燬方法 
    public void myDestroy() {
        System.out.println("myDestroy被呼叫"); 
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("setApplicationContext被呼叫");
    }

}
View Code

定義了後置處理器CusBeanPostProcessor 實現了BeanPostProcessor 介面。

package com.demo.model;

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

public class CusBeanPostProcessor 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;
    }

}

在xml中配置bean和BeanPostProcessor。

  <bean id="user" class="com.demo.model.UserBean" destroy-method="myDestroy" init-method="myInit">
      <property name="name" value="abc"></property>
  </bean> 
  <bean id="postProcessor" class="com.demo.model.CusBeanPostProcessor" />

測試:

        ApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
        BeanFactory factory=context;
        UserBean user=(UserBean)context.getBean("user");
        ((ClassPathXmlApplicationContext)context).close();

輸出結果:
UserBean類構造方法
set方法被呼叫
BeanNameAware被呼叫
BeanFactoryAware被呼叫
setApplicationContext被呼叫
postProcessBeforeInitialization被呼叫
InitializingBean被呼叫
myInit被呼叫
postProcessAfterInitialization被呼叫
DisposableBean被呼叫
myDestroy被呼叫

相關推薦

SpringBean作用生命週期

在前面部落格中提到容器啟動獲得BeanDefinition物件中有一個scope 屬性。該屬性控制著bean物件的作用域。本章節介紹Bean的作用域及生命週期,瞭解bean是怎麼來的又怎麼沒的。 一、Bean的作用域在Bean容器啟動會讀取bean的xml配置檔案,然後將xml中每個bean元素分別轉換成Be

【第三章】 DI 3.4 Bean作用生命週期

3.4  Bean的作用域         什麼是作用域呢?即“scope”,在面向物件程式設計中一般指物件或變數之間的可見範圍。而在Spring容器中是指其建立的Bean物件相對於其他Bean物件的請求可見範圍。       Spring提供“singleton”和“p

spring作用生命週期簡介

1. spring 作用域 使用scope屬性指定bean的作用域,預設值為singleton singleton 即單例模式,每次返回都是同一個bean prototype 原型模式,每次都會重新生成一個新的bean例項 2. bean生命週期簡介

C++ 作用生命週期 靜態static

1⃣️靜態區域性變數作用域不變,生命週期延長至程式執行結束 2⃣️靜態全域性變數作用域變小,不能extern引用,生命週期不變 類中的靜態成員:成員函式,成員變數都是使用物件來進行呼叫, 也有些資料成員和成員函式屬於整個類,稱這些成員為類的靜態成員(這些成員不屬於物件,建立

C++中變數的作用生命週期

     今天在論壇上看到有朋友發帖問道:既然靜態全域性變數與全域性變數都儲存在全域性資料區,為什麼作用域卻不一樣呢?也許答案非常簡單:C++就是這麼規定的,靜態全域性變數與全域性變數的唯一區別就是作用域不同。      對一個C++變數來說,有兩個屬性非常重要:作用域和生命

C++的基礎知識(十四)--變數的作用生命週期

生命週期 變數的生命週期指可以使用變數儲存位置的時間範圍 變數的儲存位置在程式執行期間不停地被建立又不停被回收 根據生命週期也可以把變數分為全域性,區域性和塊 全域性變數的生命週期是整個程式執行期間 區域性變數的生命週期是函式呼叫期間 塊變數的生命週期

Springbean作用(JAVASE)

在 Spring 中, 可以在 元素的 scope 屬性裡設定 Bean 的作用域。 預設情況下, Spring 只為每個在 IOC 容器裡宣告的 Bean 建立唯一一個例項,整個 IOC 容器範圍內都能共享該例項:所有後續的 getBean() 呼叫和 B

C的變數型別、作用生命週期的總結

# C的變數型別、作用域與生命週期的總結 最近在看“C Programing Language" (Kernighan, Ritchie)關於外部變數的討論,之前在學C的時候對這些extern, auto, static, register等不是太理解,這本書講的很詳細,現在總結一下。 首先, C的變數分

SpringBean作用生命周期

src efi lin 控制 初始化 troy [] 分享 isp 在前面博客中提到容器啟動獲得BeanDefinition對象中有一個scope 屬性。該屬性控制著bean對象的作用域。本章節介紹Bean的作用域及生命周期,了解bean是怎麽來的又怎麽沒的。 一、Bean

springbean作用生命週期

spring中bean的作用域: 生命週期(官方圖): spring 中bean例項化過程(不好意思,我盜圖了): 1:instantiate bean物件例項化 2:populate properties 封裝屬性 3:如果Bean實現BeanNameAwar

嵌入式C語言深度解讀C語言的儲存作用生命週期,連結屬性

***儲存類:    就是儲存型別,描述,C語言變數的儲存地址。    記憶體的管理方式:棧  堆  資料段  bss段  .text段。    一個變數的儲存型別就是描述這個變數儲存在何種記憶體段之

springscope作用

tle .cn lob height 模式 新建 應用 let image spring中,bean的作用域有五種類型:默認是單例模式, singleton prototype request session

C語言高階篇 - 3.儲存類&作用&生命週期&連結屬性

1.概念解析 1.1、儲存類         (1)儲存類就是儲存型別,也就是描述C語言變數在何種地方儲存。         (2)記憶體有多種管理方法:棧、堆、資料段、bss段、.text段······一個

[MyBatis] 主要類的作用生命週期

主要類的作用域和生命週期 SqlSessionFactoryBuilder SqlSessionFactory SqlSession 對映器例項(Mapper Instances) 理解以上類的不同作用域和生命週期類是至關重要的,因為錯誤的使用會導致非

深入學習JavaScript函式作用作用

  我們將作用域比作氣泡,一層巢狀一層,每一個氣泡裡面都可以放置識別符號(函式,變數)的定義,這些氣泡在書寫階段就已經確定了。   但是,究竟是什麼生成了一個新的氣泡,只有函式能夠生成氣泡嗎?JavaScipt中的其他結構能生成作用域氣泡嗎? 1.1  函式中的

SpringBean作用 scope屬性指定Bean是否為單例物件

Bean作用域: 預設屬性scope="singleton"表示容器初始化建立這一個Bean 單例的 Hello person1 = (Hello) applicationContext.get

java 區域性變數,類變數,例項變數的作用生命週期

1,區域性變數 區域性變數是指定義在方法或程式碼塊中的變數,區域性變數必須初始化,在方法或程式碼塊內有效,之外則無效,方法執行開始入棧時建立,執行完畢出棧時銷燬。 2,例項變數 其作用域受限定符限定,Private的只能在本類中使用,protected子類可用,publi

Spring框架Bean作用

Spring框架現有的Bean作用域 ( 1 ) singleton :預設的作用域,僅為每個 Bean 物件建立一個例項。 ( 2 ) prototype :可以根據需要為每個 Bean 物件建立多個例項。 ( 3 ) request :為每個 HTTP 請求建立

MyBatis中的作用生命週期

SqlSessionFactoryBuilder        這個類可以被例項化,使用和丟棄,一旦建立了SqlSessionFactory,就不再需要它,因此SqlSessionFactoryBuilder例項的最佳作用域是方法作用域(也就是區域性方法變數)。可以重用Sql

Mybatis學習-配置、作用生命週期

**核心配置檔案**:Mybatis-config.xml Mybatis的配置檔案包含了會深深影響Mybatis行為的設定和屬性資訊 ## 配置(configuration) > 在mybatis-config.xml檔案中標籤都有規定的順序,需要按照以下順序新增 properties?,setting