在前面博客中提到容器启动获得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实例。只在基于web的Spring ApplicationContext中可用

会话(session)

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

全局会话(global session)

限定一个Bean的作用域为全局HTTPSession的生命周期。通常用于门户网站场景,同样,只有基于web的Spring 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被调用");
} }

定义了后置处理器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被调用

Spring之Bean的作用域与生命周期的更多相关文章

  1. 详解Spring中Bean的作用域与生命周期

    摘要:在利用Spring进行IOC配置时,关于bean的配置和使用一直都是比较重要的一部分,同时如何合理的使用和创建bean对象,也是小伙伴们在学习和使用Spring时需要注意的部分,所以这一篇文章我 ...

  2. Spring中Bean的作用域、生命周期

                                   Bean的作用域.生命周期 Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).protot ...

  3. Spring中bean的作用域与生命周期

    在 Spring 中,那些组成应用程序的主体及由 Spring IOC 容器所管理的对象,被称之为 bean.简单地讲,bean 就是由 IOC 容器初始化.装配及管理的对象,除此之外,bean 就与 ...

  4. Spring中Bean的作用域和生命周期

    作用域的种类 Spring 容器在初始化一个 Bean 的实例时,同时会指定该实例的作用域.Spring3 为 Bean 定义了五种作用域,具体如下. 1)singleton 单例模式,使用 sing ...

  5. Spring bean的作用域和生命周期

    bean的作用域 1.singleton,prototype, web环境下:request,session,gloab session 2.通过scope="" 来进行配置 3. ...

  6. Spring框架系列(三)--Bean的作用域和生命周期

    Bean的作用域 Spring应用中,对象实例都是在Container中,负责创建.装配.配置和管理生命周期(new到finalize()) Spring Container分为两种: 1.BeanF ...

  7. Spring bean的作用域以及生命周期

    一.request与session的区别 request简介 request范围较小一些,只是一个请求. request对象的生命周期是针对一个客户端(说确切点就是一个浏览器应用程序)的一次请求,当请 ...

  8. Spring ( 三 ) Spring的Bean的装配与生命周期、专用测试

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.对象的生命周期 1.IOC之Bean的生命周期 创建带有生命周期方法的bean public cla ...

  9. bean的作用域和生命周期

    一.Bean作用域 二.生命周期 其中,这个类实现各种接口重写各种方法,会按bean的声明周期按序执行: 其中,自定义的初始化和自定义销毁的方法不是实现接口重写,而是成员方法,并且在装配bean即在x ...

随机推荐

  1. Python3基础知识之数据结构List和Tuple

    问题:今天学习python数据结构中的List和Tuple. 目标:了解二者的区别,学会一般的应用 相关知识:列表(List) : 类似于 .NET ArrayList / List.元组(Tuple ...

  2. P3379 【模板】最近公共祖先(LCA)(树链剖分)版

    #include <bits/stdc++.h> #define read read() #define up(i,l,r) for(register int i = (l);i < ...

  3. 解决跨域脚本攻击 XSS

    配置Content Security Policy    传送门:作者: 阮一峰 http://www.ruanyifeng.com/blog/2016/09/csp.html [前端安全]JavaS ...

  4. A - ACboy needs your help again!

    ACboy was kidnapped!! he miss his mother very much and is very scare now.You can't image how dark th ...

  5. ABP框架系列之三十六:(MVC-Views-MVC视图)

    Introduction ASP.NET Boilerplate is integrated to MVC Views via Abp.Web.Mvc nuget package. You can c ...

  6. php判断语句

    编写代码时,可以为不同的情况执行不同的动作.可以使用判断条件语句来实现. if...else...elseif 例子一: <?php $t=date("H"); if ($t ...

  7. Django URLConf 进阶

    Django处理一个请求 项目启动后根据 settings  ROOT_URLCONF 决定项目根URLconf urlpatterns是django.conf.urls.url()实例的一个Pyth ...

  8. 我知道的nginx配置

    1.nginx配置文件 2.配置访问域名 #京淘商品管理系统 server { listen 80; server_name manage.jt.com; location / { proxy_pas ...

  9. SSD报告 - QRadar远程命令执行

    SSD报告 - QRadar远程命令执行 漏洞摘要 QRadar中的多个漏洞允许远程未经身份验证的攻击者使产品执行任意命令.每个漏洞本身并不像链接那么强大 - 这允许用户从未经身份验证的访问更改为经过 ...

  10. vs2017 遇到异常。这可能是由某个扩展导致的。奇妙的解决方式

    最近在使用visual studio 2017 创建.netcore 2.2的MVC项目后,在View里面拖拽引用css或js文件时总出现“遇到异常.这可能是由某个扩展导致的.” 然后在网上找了大半天 ...