Spring學習--Bean的作用域
阿新 • • 發佈:2018-12-07
**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時講解具體使用,大家只需要知道有這些作用域就可以了。