Spring Bean生命周期,好像人的一生~~
今天带领大家一起学习Spring Bean的一生~~
目录
什么是Spring Bean生命周期?
在Spring中,基本容器BeanFactory和扩展容器ApplicationContext的实例化时机不太一样,BeanFactory采用的是延迟初始化的方式,也就是只有在第一次getBean()的时候,才会实例化Bean;ApplicationContext启动之后会实例化所有的Bean定义。
Spring IOC 中Bean的生命周期大致分为四个阶段:实例化(Instantiation)、属性赋值(Populate)、初始化(Initialization)、销毁(Destruction)。
Bean生命周期四个阶段
我们再来看一个稍微详细一些的过程:
-
实例化:第 1 步,实例化一个 Bean 对象
-
属性赋值:第 2 步,为 Bean 设置相关属性和依赖
-
初始化:初始化的阶段的步骤比较多,5、6步是真正的初始化,第 3、4 步为在初始化前执行,第 7 步在初始化后执行,初始化完成之后,Bean就可以被使用了
-
销毁:第 8~10步,第8步其实也可以算到销毁阶段,但不是真正意义上的销毁,而是先在使用前注册了销毁的相关调用接口,为了后面第9、10步真正销毁 Bean 时再执行相应的方法
简单总结一下,Bean生命周期里初始化的过程相对步骤会多一些,比如前置、后置的处理。
最后通过一个实例来看一下具体的细节:
-
定义一个
PersonBean
类,实现DisposableBean
,?InitializingBean
,BeanFactoryAware
,BeanNameAware
这4个接口,同时还有自定义的init-method
和destroy-method
。public?class?PersonBean?implements?InitializingBean,?BeanFactoryAware,?BeanNameAware,?DisposableBean?{
???/**
????身份证号
???/
???private?Integer?no;???/**
????姓名
???/
???private?String?name;???public?PersonBean()?{
???System.out.println(“1.调用构造方法:我出生了!”);
???}???public?Integer?getNo()?{
???return?no;
???}???public?void?setNo(Integer?no)?{
???this.no?=?no;
???}???public?String?getName()?{
???return?name;
???}???public?void?setName(String?name)?{
???this.name?=?name;
???System.out.println(“2.设置属性:我的名字叫”+name);
???}???@Override
???public?void?setBeanName(String?s)?{
???System.out.println(“3.调用BeanNameAware#setBeanName方法:我要上学了,起了个学名”);
???}???@Override
???public?void?setBeanFactory(BeanFactory?beanFactory)?throws?BeansException?{
???System.out.println(“4.调用BeanFactoryAware#setBeanFactory方法:选好学校了”);
???}???@Override
???public?void?afterPropertiesSet()?throws?Exception?{
???System.out.println(“6.InitializingBean#afterPropertiesSet方法:入学登记”);
???}???public?void?init()?{
???System.out.println(“7.自定义init方法:努力上学ing”);
???}???@Override
???public?void?destroy()?throws?Exception?{
???System.out.println(“9.DisposableBean#destroy方法:平淡的一生落幕了”);
???}???public?void?destroyMethod()?{
???System.out.println(“10.自定义destroy方法:睡了,别想叫醒我”);
???}???public?void?work(){
???System.out.println(“Bean使用中:工作,只有对社会没有用的人才放假。。”);
???}}
-
定义一个
MyBeanPostProcessor
实现BeanPostProcessor
接口。 -
public?class?MyBeanPostProcessor?implements?BeanPostProcessor?{ ????@Override ????public?Object?postProcessBeforeInitialization(Object?bean,?String?beanName)?throws?BeansException?{ ????????System.out.println("5.BeanPostProcessor.postProcessBeforeInitialization方法:到学校报名啦"); ????????return?bean; ????} ????@Override ????public?Object?postProcessAfterInitialization(Object?bean,?String?beanName)?throws?BeansException?{ ????????System.out.println("8.BeanPostProcessor#postProcessAfterInitialization方法:终于毕业,拿到毕业证啦!"); ????????return?bean; ????} }
-
配置文件,指定
init-method
和destroy-method
属性 -
<?xml?version="1.0"?encoding="UTF-8"?> <beans?xmlns="http://www.springframework.org/schema/beans" ???????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ???????xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans.xsd"> ????<bean?name="myBeanPostProcessor"?class="cn.fighter3.spring.life.MyBeanPostProcessor"?/> ????<bean?name="personBean"?class="cn.fighter3.spring.life.PersonBean" ??????????init-method="init"?destroy-method="destroyMethod"> ????????<property?name="idNo"?value=?"80669865"/> ????????<property?name="name"?value="张铁钢"?/> ????</bean> </beans>
-
测试
-
public?class?Main?{ ????public?static?void?main(String[]?args)?{ ????????ApplicationContext?context?=?new?ClassPathXmlApplicationContext("spring-config.xml"); ????????PersonBean?personBean?=?(PersonBean)?context.getBean("personBean"); ????????personBean.work(); ????????((ClassPathXmlApplicationContext)?context).destroy(); ????} }
-
运行结果:
-
1.调用构造方法:我出生了! 2.设置属性:我的名字叫张铁钢 3.调用BeanNameAware#setBeanName方法:我要上学了,起了个学名 4.调用BeanFactoryAware#setBeanFactory方法:选好学校了 5.BeanPostProcessor#postProcessBeforeInitialization方法:到学校报名啦 6.InitializingBean#afterPropertiesSet方法:入学登记 7.自定义init方法:努力上学ing 8.BeanPostProcessor#postProcessAfterInitialization方法:终于毕业,拿到毕业证啦! Bean使用中:工作,只有对社会没有用的人才放假。。 9.DisposableBean#destroy方法:平淡的一生落幕了 10.自定义destroy方法:睡了,别想叫醒我
关于源码,Bean创建过程可以查看
AbstractBeanFactory#doGetBean
方法,在这个方法里可以看到Bean的实例化,赋值、初始化的过程,至于最终的销毁,可以看看ConfigurableApplicationContext#close()
。Bean生命周期源码追踪
参考文献:
Bean容器生命周期,好像人的一生。。?
本期分享到此为止,别忘了给点点关注,关注博主不迷路,带你上高速~~
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦