1. 程式人生 > >Spring學習--Bean的作用域

Spring學習--Bean的作用域

**Bean的作用域**:
    作用域:一般指的是物件或者變數之間的可見範圍。而在Spring容器中是指其建立的Bean物件相對於其他Bean物件的請求可見範圍。
        Spring提供Singleton和prototype兩種基本作用域,另外提供Request、session、global、session三種web作用域;Spring還允許使用者制定自己的作用域。
    基本的作用域
        **一:Singleton:**指Singleton作用域的Bean只會在每個S平IOC容器中存在一個例項,而且其完整生命週期完全由Spring容器管理。對於所有獲取Bean的操作Spring容器將只返回同一個Bean。

            GoF單例設計模式指“保證一個類僅有一個例項,並提供一個訪問它的全域性訪問點”,介紹了兩種實現:通過在類上定義靜態屬性保持該例項和通過登錄檔方式。

            **1
)通過在類上定義靜態屬性保持該例項**:一般指一個Java虛擬機器 ClassLoader裝載的類只有一個例項,一般通過類靜態屬性保持該例項,這樣就造成需要單例的類都需要按照單例設計模式進行編碼;Spring沒采用這種方式,因為該方式屬於侵入式設計; package org.liang.test; /** * 單例類 */ public class Singleton { private String name; private
Singleton(){}; public static Singleton getInstance(){ return new Singleton(); } public String getName() { return name; } public void setName(String name) { this
.name = name; } } class TsetSingleton{ public static void main(String [] args){ Singleton singleton = Singleton.getInstance(); singleton.setName("關羽"); System.out.println(singleton.getName()); } } **2) 通過登錄檔方式:** 首先將需要單例的例項通過唯一鍵註冊到登錄檔,然後通過鍵來獲取單例,讓我們直接看實現吧,注意本登錄檔實現了Spring介面“SingletonBeanRegistry”,該介面定義了操作共享的單例物件,Spring容器實現將實現此介面;所以共享單例物件通過“registerSingleton”方法註冊,通過“getSingleton”方法獲取,消除了程式設計方式單例,注意在實現中不考慮併發。 package org.liang.test; import org.liang.entity.Persion; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Created by rcc on 2018/2/2. */ public class TestScope { public static void main(String [] args){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); Persion persion = context.getBean(Persion.class); Persion persion1 = context.getBean(Persion.class); System.out.println(persion == persion1); System.out.println("======================================================="); Persion persion2 = new Persion(); Persion persion3 = new Persion(); System.out.println(persion2 == persion3); System.out.println("======================================================="); System.out.println(persion); System.out.println(persion1); /** * 返回結果: * true *====================================================== * false * * 這就很奇怪了是不是,使用容器獲得的兩個所謂的新的物件居然是同一個物件,這和我們直接new兩個物件的結果剛好相反。 * 不過仔細想一想也不奇怪,既然物件是從Spring容器中獲取的,會不會是容器在物件建立的時候對物件進行了快取呢? * * 基於這個猜想,我們將物件中的屬性打印出來: * * Persion{name='doudou', nickName='zhuzhu', age=18} * Persion{name='doudou', nickName='zhuzhu', age=18} * 結果居然一模一樣,返回的是同一個物件。 * * 那麼這到底是什麼原因呢? * <bean id="persion" class="org.liang.entity.Persion" scope="singleton"> <constructor-arg index="0" value="doudou"/> <constructor-arg name="nickName" value="zhuzhu"/> <constructor-arg type="java.lang.Integer" value="18"/> </bean> * 原因就是這個配置:scope="singleton" ,表示該物件是單例的,所以容器會快取物件,每次獲取的物件都是同一個。 * 在Spring容器中如果沒指定作用域預設就是“singleton”。 */ } } **二、prototype:即原型,**指每次向Spring容器請求獲取Bean都返回一個全新的Bean,相對於“singleton”來說就是不快取Bean,每次都是一個根據Bean定義建立的全新Bean。 <bean id="user" class="org.liang.entity.User" scope="prototype"> <property name="name" value="張三"/> <property name="gender" value="男"/> <property name="age" value="18"/> </bean> ======================================================================================== User user = (User) context.getBean("user"); User user1 = (User) context.getBean("user"); System.out.println(user == user1); /** 返回結果: * ======================================================= false :每次獲取的都是全新的物件 */ **Web應用中的作用域:** 在Web應用中,我們可能需要將資料儲存到request、session、global session。因此Spring提供了三種Web作用域:request、session、globalSession。 一、request作用域:表示每個請求需要容器建立一個全新Bean。比如提交表單的資料必須是對每次請求新建一個Bean來保持這些表單資料,請求結束釋放這些資料。 二、session作用域:表示每個會話需要容器建立一個全新Bean。比如對於每個使用者一般會有一個會話,該使用者的使用者資訊需要儲存到會話中,此時可以將該Bean配置為web作用域。 三、globalSession:類似於session作用域,只是其用於portlet環境的web應用。如果在非portlet環境將視為session作用域。 配置方式和基本的作用域相同,只是必須要有web環境支援,並配置相應的容器監聽器或攔截器從而能應用這些作用域,我們會在整合web時講解具體使用,大家只需要知道有這些作用域就可以了。