一文搞懂Spring Bean中的作用域和生命周期
一、Spring Bean 作用域
常規(guī)的 Spring IoC 容器中Bean的作用域有兩種:singleton(單例)和prototype(非單例)
注:基于Web的容器還有其他種作用域,在這就不贅述了。
singleton(單例)
singleton是Spring默認(rèn)的作用域。當(dāng) Bean 的作用域為 singleton 時,Spring IoC 容器中只會存在一個共享的 Bean 實例??梢愿玫刂赜脤ο螅?jié)省重復(fù)創(chuàng)建對象的開銷。- 設(shè)置方式:將 <bean> 元素的 scope 屬性設(shè)置為
singleton(其實也可以不用設(shè)置,因為spring默認(rèn)就是單例模式)
案例1
1.創(chuàng)建Dept類
public class Dept {
//部門編號
private int deptNo;
//部門名稱
private String deptName;
}
2.編寫Spring配置文件,并將scope 屬性設(shè)置為singleton
<bean id="dept" class="com.bighorn.pojo.Dept" scope="singleton"> </bean>
3.編寫運行程序
public static void main(String[] args) {
//獲取IoC容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//從容器中獲取對象
Dept dept1 = context.getBean("dept", Dept.class);
Dept dept2 = context.getBean("dept", Dept.class);
//打印對象
System.out.println(dept1);
System.out.println(dept2);
}
4.結(jié)果如下,可以發(fā)現(xiàn)打印出的是同一個對象

prototype(原型)
prototype表示原型(非單例)模式。當(dāng) Bean 的作用域為 prototype時,Spring 容器會在每次請求該 Bean 時,都創(chuàng)建一個新的 Bean 實例。- 設(shè)置方式:將 <bean> 元素的 scope 屬性設(shè)置為
prototype
案例2
1.只需修改scope 屬性為prototype,其他代碼不變。
<bean id="dept" class="com.bighorn.pojo.Dept" scope="prototype"> </bean>
2.運行結(jié)果如下

小結(jié)
spring bean默認(rèn)為單例,避免了對象的頻繁創(chuàng)建與銷毀,達(dá)到了bean對象的復(fù)用,性能高。
像表現(xiàn)層、業(yè)務(wù)層、數(shù)據(jù)層、工具類對象只需要調(diào)用方法,比較適合交給Spring IoC容器管理
但是像那種需要封裝實例的域?qū)ο?,因為會引發(fā)線程安全問題,不適合交給Spring IoC容器管理。
二、Spring Bean生命周期
Spring Bean生命周期:Spring Bean 對象從創(chuàng)建到銷毀的整體過程。
Spring Bean生命周期大致可以分為以下 5 個階段:1.Bean 的實例化、2.Bean 屬性賦值、3.Bean 的初始化、4.Bean 的使用、5.Bean 的銷毀
Spring 根據(jù) Bean 的作用域來選擇 Bean 的管理方式。
- 對于 singleton 作用域的 Bean ,Spring IoC 容器能夠一直追蹤bean的生命周期;
- 對于 prototype 作用域的 Bean ,Spring IoC 容器只負(fù)責(zé)創(chuàng)建,然后就將 Bean 的實例交給客戶端代碼管理,Spring IoC 容器將不再跟蹤其生命周期。
綜上所述: 為了更好研究如何控制bean周期,下面案例中創(chuàng)建的bean默認(rèn)都使用單例模式。
如何關(guān)閉容器
由于ApplicationContext類中沒有關(guān)閉容器的方法,所以想要關(guān)閉容器需要用到ApplicationContext的子類——ClassPathXmlApplicationContext類。該類又有兩種方法可以關(guān)閉容器
1、close關(guān)閉容器
close()方法,在調(diào)用的時候關(guān)閉容器
//獲取 ClassPathXmlApplicationContext 容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//調(diào)用close方法關(guān)閉容器
context.close();
2、注冊鉤子關(guān)閉容器
registerShutdownHook()方法,在JVM退出前調(diào)用關(guān)閉容器
//獲取 ClassPathXmlApplicationContext 容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//調(diào)用注冊狗子關(guān)閉容器
context.registerShutdownHook();
生命周期回調(diào)
Bean 的生命周期回調(diào)方法主要有兩種:
- 初始化回調(diào)方法:在 Spring Bean 被初始化后調(diào)用,執(zhí)行一些自定義的回調(diào)操作。
- 銷毀回調(diào)方法:在 Spring Bean 被銷毀前調(diào)用,執(zhí)行一些自定義的回調(diào)操作。
我們可以通過以下 2種方式自定義 Bean 的生命周期回調(diào)方法:
- 通過接口實現(xiàn)
- 通過 XML 配置實現(xiàn)
通過接口設(shè)置生命周期
我們可以在 Spring Bean 的 Java 類中,通過實現(xiàn) InitializingBean 和 DisposableBean 接口,指定 Bean 的生命周期回調(diào)方法。
案例1
1.創(chuàng)建User類,并實現(xiàn)InitializingBean, DisposableBean接口,重寫afterPropertiesSet()和destroy()方法。代碼如下
/**
* 繼承接口,程序初始化回調(diào)和銷毀回調(diào)方法
*/
public class User implements InitializingBean, DisposableBean {
String name;
int age;
//setter方法
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
//初始化回調(diào)方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("這是初始化回調(diào)方法");
}
//銷毀回調(diào)方法
@Override
public void destroy() throws Exception {
System.out.println("這是銷毀回調(diào)方法");
}
//toString方法
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.編寫spring配置文件
<bean id="user" class="com.bighorn.pojo.User">
<property name="name" value="bighorn"/>
<property name="age" value="18"/>
</bean>
3.編寫運行程序
public class App {
public static void main(String[] args) {
//獲取 ClassPathXmlApplicationContext 容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//從容器中獲取對象
User user = context.getBean("user", User.class);
//使用bean
System.out.println(user);
//調(diào)用close方法關(guān)閉容器
context.close();
}
}
4.運行結(jié)果如下

通過xml設(shè)置生命周期
注意:由于通過接口設(shè)置生命周期的方式會導(dǎo)致代碼的耦合性過高,所以通常情況下,我們會通過xml設(shè)置生命周期。
通過 <bean> 元素中的 init-method 和 destory-method 屬性,指定 Bean 的生命周期回調(diào)方法。
案例2
1.創(chuàng)建User類,這次不需要繼承那兩個接口了,但要在添加兩個普通方法(方法名可任意):init()和destory()代表初始化和銷毀方法。代碼如下
/**
* 通過XML配置指定回調(diào)方法
*/
public class User {
String name;
int age;
//setter方法
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
//初始化回調(diào)方法
public void init() throws Exception {
System.out.println("這是初始化回調(diào)方法");
}
//銷毀回調(diào)方法
public void destroy() throws Exception {
System.out.println("這是銷毀回調(diào)方法");
}
//toString方法
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.編寫spring配置文件,在<bean>元素里添加init-method和destroy-method屬性,并指定User類中自定義的init和destory方法(關(guān)鍵)
<!--通過XML配置指定回調(diào)方法-->
<bean id="user" class="com.bighorn.pojo.User" init-method="init" destroy-method="destroy">
<property name="name" value="bighorn"/>
<property name="age" value="18"/>
</bean>
3.運行程序和運行結(jié)果都與案例1相同,這里就少些筆墨介紹了
到此這篇關(guān)于一文搞懂Spring Bean中的作用域和生命周期的文章就介紹到這了,更多相關(guān)Spring Bean作用域 生命周期內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java數(shù)據(jù)機構(gòu)中關(guān)于并查集的詳解
并查集是一種樹型的數(shù)據(jù)結(jié)構(gòu),用于處理一些不相交集合的合并及查詢問題,如果你還不了解并查集,請看接下來的文章,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值2021-09-09
詳解servlet的url-pattern匹配規(guī)則
本篇文章主要介紹了=servlet的url-pattern匹配規(guī)則,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12
Windows下Java調(diào)用可執(zhí)行文件代碼實例
這篇文章主要介紹了Windows下Java調(diào)用可執(zhí)行文件代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-12-12

