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

Version:1.0 StartHTML:000000209 EndHTML:000019387 StartFragment:000001892 EndFragment:000019301 StartSelection:000001892 EndSelection:000019291 SourceURL:https://www.cnblogs.com/5ishare/p/9532057.html <title>Spring之Bean的作用域與生命周期 - 社會主義接班人 - 博客園</title><link href="/bundles/blog-common.css?v=PX31qVjOE47mNaZI9JUSFK-ajuzMnpXA9PeteRNR1Qw1" rel="stylesheet" type="text/css"><link id="MainCss" href="/skins/red_autumnal_leaves/bundle-red_autumnal_leaves.css?v=EDEp2d1uMe8iyN6qDoW8MQgYb-JCFIeiYP0oX3XiiRM1" rel="stylesheet" type="text/css"><link id="mobile-style" href="/skins/red_autumnal_leaves/bundle-red_autumnal_leaves-mobile.css?v=d9LctKHRIQp9rreugMcQ1-UJuq_j1fo0GZXTXj8Bqrk1" rel="stylesheet" type="text/css" media="only screen and (max-width: 767px)"><link title="RSS" rel="alternate" type="application/rss+xml"><link title="RSD" rel="EditURI" type="application/rsd+xml"><link rel="wlwmanifest" type="application/wlwmanifest+xml"> <script type="text/javascript">var currentBlogApp = '5ishare', cb_enable_mathjax=false;var isLogined=true;</script>

在前面博客中提到容器啟動獲得BeanDefinition對象中有一個scope 屬性。該屬性控制著bean對象的作用域。本章節(jié)介紹Bean的作用域及生命周期,了解bean是怎么來的又怎么沒的。

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

|

作用域

|

描述

|
|

單例(singleton)

|

(默認)每一個Spring IoC容器都擁有唯一的一個實例對象

|
|

原型(prototype)

|

一個Bean定義,任意多個對象

|
|

請求(request)

|

一個HTTP請求會產(chǎn)生一個Bean對象,也就是說,每一個HTTP請求都有自己的Bean實例。只在基于web的Spring ApplicationContext中可用

|
|

會話(session)

|

限定一個Bean的作用域為HTTPsession的生命周期。同樣,只有基于web的Spring ApplicationContext才能使用

|
|

全局會話(global session)

|

限定一個Bean的作用域為全局HTTPSession的生命周期。通常用于門戶網(wǎng)站場景,同樣,只有基于web的Spring ApplicationContext可用

|

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

<pre> XMLInstance instance=(XMLInstance)factory.getBean("xmlinstance");
instance.setName("123");
instance.Breath();
instance=(XMLInstance)factory.getBean("xmlinstance");
instance.Breath();</pre>

如果我們采用bean默認的作用域singleton,如下配置,則兩個getbean獲取的對象是一致的。

<pre> <bean id="xmlinstance" class="com.demo.model.XMLInstance" scope="singleton">
<property name="air" ref="CleanAir"></property>
<property name="name" value="abc"></property>
</bean></pre>

<pre>輸出結果:
Name:123;Air:CleanAir
Name:123;Air:CleanAir</pre>

如果我們采用bean默認的作用域singleton,如下配置,則兩個getbean獲取的對象是不一致的。

<pre> <bean id="xmlinstance" class="com.demo.model.XMLInstance" scope="prototype">
<property name="air" ref="CleanAir"></property>
<property name="name" value="abc"></property>
</bean></pre>

<pre>輸出結果:
Name:123;Air:CleanAir
Name:abc;Air:CleanAir</pre>

二、Bean的生命周期
前面章節(jié)介紹了bean容器以及bean的配置與注入,本章節(jié)學習bean的生命周期,了解bean是怎么來的又是怎么沒的。

image

ApplicationContext容器中,Bean的生命周期流程如上圖所示,流程大致如下:
1.首先容器啟動后,會對scope為singleton且非懶加載的bean進行實例化,
2.按照Bean定義信息配置信息,注入所有的屬性,
3.如果Bean實現(xiàn)了BeanNameAware接口,會回調(diào)該接口的setBeanName()方法,傳入該Bean的id,此時該Bean就獲得了自己在配置文件中的id,
4.如果Bean實現(xiàn)了BeanFactoryAware接口,會回調(diào)該接口的setBeanFactory()方法,傳入該Bean的BeanFactory,這樣該Bean就獲得了自己所在的BeanFactory,
5.如果Bean實現(xiàn)了ApplicationContextAware接口,會回調(diào)該接口的setApplicationContext()方法,傳入該Bean的ApplicationContext,這樣該Bean就獲得了自己所在的ApplicationContext,
6.如果有Bean實現(xiàn)了BeanPostProcessor接口,則會回調(diào)該接口的postProcessBeforeInitialzation()方法,
7.如果Bean實現(xiàn)了InitializingBean接口,則會回調(diào)該接口的afterPropertiesSet()方法,
8.如果Bean配置了init-method方法,則會執(zhí)行init-method配置的方法,
9.如果有Bean實現(xiàn)了BeanPostProcessor接口,則會回調(diào)該接口的postProcessAfterInitialization()方法,
10.經(jīng)過流程9之后,就可以正式使用該Bean了,對于scope為singleton的Bean,Spring的ioc容器中會緩存一份該bean的實例,而對于scope為prototype的Bean,每次被調(diào)用都會new一個新的對象,期生命周期就交給調(diào)用方管理了,不再是Spring容器進行管理了
11.容器關閉后,如果Bean實現(xiàn)了DisposableBean接口,則會回調(diào)該接口的destroy()方法,
12.如果Bean配置了destroy-method方法,則會執(zhí)行destroy-method配置的方法,至此,整個Bean的生命周期結束。

這里在UserBean類基礎上進行改造,增加了name屬性并實現(xiàn)了ApplicationContextAware接口。

image
image

<pre>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方法被調(diào)用");
} public UserBean() {
System.out.println("UserBean類構造方法");
} public void setBeanName(String name) {
System.out.println("BeanNameAware被調(diào)用");
} public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryAware被調(diào)用");
} public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean被調(diào)用");
} public void destroy() throws Exception {
System.out.println("DisposableBean被調(diào)用");
} //自定義的初始化函數(shù)
public void myInit() {
System.out.println("myInit被調(diào)用");
} //自定義的銷毀方法
public void myDestroy() {
System.out.println("myDestroy被調(diào)用");
} public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("setApplicationContext被調(diào)用");
}

}</pre>

View Code

定義了后置處理器CusBeanPostProcessor 實現(xiàn)了BeanPostProcessor 接口。

[[圖片上傳失敗...(image-60f7f6-1535123798917)]](javascript:void(0); "復制代碼")

<pre>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被調(diào)用"); return bean;

} public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("postProcessAfterInitialization被調(diào)用"); return bean;
}

}</pre>

[[圖片上傳失敗...(image-877b6a-1535123798917)]](javascript:void(0); "復制代碼")

在xml中配置bean和BeanPostProcessor。

<pre> <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" /></pre>

測試:

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

輸出結果:
UserBean類構造方法
set方法被調(diào)用
BeanNameAware被調(diào)用
BeanFactoryAware被調(diào)用
setApplicationContext被調(diào)用
postProcessBeforeInitialization被調(diào)用
InitializingBean被調(diào)用
myInit被調(diào)用
postProcessAfterInitialization被調(diào)用
DisposableBean被調(diào)用
myDestroy被調(diào)用

image
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,525評論 19 139
  • 1.1 Spring IoC容器和bean簡介 本章介紹了Spring Framework實現(xiàn)的控制反轉(IoC)...
    起名真是難閱讀 2,665評論 0 8
  • 1.1 spring IoC容器和beans的簡介 Spring 框架的最核心基礎的功能是IoC(控制反轉)容器,...
    simoscode閱讀 6,846評論 2 22
  • 今天是首屆情商行業(yè)大會,在南京盛大開啟。身未動心已抵達,通過四面八方的視頻,相片,文字傳播,內(nèi)心很激動。齙牙兔做情...
    情商教育章佳靈閱讀 327評論 0 0
  • 因溇而生,因港而興。溇港文化沉淀了千年后,漸漸地被世人所矚目?!吧h黥~躍處,捧卷看青山”社會實踐團來到溇港文化最具...
    生態(tài)文明閱讀 442評論 0 0

友情鏈接更多精彩內(nèi)容