博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring之Bean的作用域与生命周期
阅读量:6256 次
发布时间:2019-06-22

本文共 5184 字,大约阅读时间需要 17 分钟。

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

会话(session

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

全局会话(global session

限定一个Bean的作用域为全局HTTPSession的生命周期。通常用于门户网站场景,同样,只有基于webSpring 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获取的对象是一致的。

输出结果:Name:123;Air:CleanAirName:123;Air:CleanAir

如果我们采用bean默认的作用域prototype,如下配置,则两个getbean获取的对象是不一致的。

输出结果:Name:123;Air:CleanAirName: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被调用");    }}
View Code

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

测试:

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被调用

 

 

转载地址:http://wynsa.baihongyu.com/

你可能感兴趣的文章
linux下node环境的搭建
查看>>
将sublime打造成python的IDE开发工具
查看>>
Mac Homebrew 利器
查看>>
Delphi中获取Unix时间戳及注意事项
查看>>
8月5日起OCP电子证书正式推行
查看>>
【原创】DataNode源码演绎 第一回
查看>>
垃圾回收概念与算法
查看>>
JDBC读取MySQL的BLOB类型
查看>>
IconFont 图标svg
查看>>
TFS实现需求工作项自动级联保存
查看>>
crontab定时执行任务
查看>>
LDAP 设置指南(转)
查看>>
软件开发--开发中的辅助工具
查看>>
mysql查询今天、昨天、7天、近30天、本月、上一月 数据
查看>>
单臂路由
查看>>
大数据工程师微职位学习分享
查看>>
企业使用云服务器的优势
查看>>
dubbo Servlet Bridge Server时同时支持hessian和webservice
查看>>
lanmp一键安装包安装说明(包括lamp,lnmp,lnamp安装)
查看>>
Shell命令-文件及内容处理之head、tail
查看>>