Spring bean 生命周期验证
一、从源码注释看bean生命周期
从JDK源码注释上看,BeanFactory实现类需要支持Bean的完整生命周期,完整的初始化方法及其标准顺序(格式:接口 方法)为:
1.BeanNameAware setBeanName 设置bean名称
2.BeanClassLoaderAware setBeanClassLoader 设置bean类加载器
3.BeanFactoryAware setBeanFactory 设置bean工厂
4.EnvironmentAware setEnvironment 设置环境:profiles+properties
5.EmbeddedValueResolverAware setEmbeddedValueResolver 设置嵌入式值解析器
6.ResourceLoaderAware setResourceLoader 设置资源载入器,只适用于在应用程序上下文中运行
7.ApplicationEventPublisherAware setApplicationEventPublisher注入应用事件发布器ApplicationEventPublisher
8.MessageSourceAware setMessageSource 设置国际化支持
9.ApplicationContextAware setApplicationContext 设置应用上下文
10.ServletContextAware setServletContext 设置servlet上下文
11.BeanPostProcessors postProcessBeforeInitialization 执行bean处理器前置方法
12.InitializingBean afterPropertiesSet 执行初始化Bean设置完属性后置方法
13.a custom init-method definition 执行自定义初始化方法
14.BeanPostProcessors postProcessAfterInitialization 执行bean处理器后置方法
销毁顺序:
1.DestructionAwareBeanPostProcessors postProcessBeforeDestruction 销毁处理器的前置方法
2.DisposableBean destroy Bean销毁回调方法
3.a custom destroy-method definition 用户自定义销毁方法
当然这里面不是所有方法都走一遍,核心方法流程图如下图:

二、测试验证
2.1分析原理
前面说的17个步骤都可以测试,我们选取其中的8个步骤进行测试如下:
初始化流程:
1.BeanNameAware setBeanName 设置bean名称
3.BeanFactoryAware setBeanFactory 设置bean工厂
11.BeanPostProcessors postProcessBeforeInitialization 执行bean处理器前置方法
12.InitializingBean afterPropertiesSet 执行初始化Bean设置完属性后置方法
13.a custom init-method definition 执行自定义初始化方法
14.BeanPostProcessors postProcessAfterInitialization 执行bean处理器后置方法
销毁流程:
2.DisposableBean destroy Bean销毁回调方法
3.a custom destroy-method definition 用户自定义销毁方法
2.2 代码清单
1.构建一个Person类,实现BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean接口。
package spring.ioc; 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; public class Person implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean { private String name; private String mobile; public Person() {
super();
System.out.println("[构造器] 调用Person的构造器实例化");
} public String getName() {
return name;
} public void setName(String name) {
System.out.println("[属性注入] name="+name);
this.name = name;
} public String getMobile() {
return mobile;
} public void setMobile(String mobile) {
System.out.println("[属性注入] mobile="+mobile);
this.mobile = mobile;
} @Override
public void destroy() throws Exception {
System.out.println("[接口DisposableBean.destroy() ]");
} @Override
public void afterPropertiesSet() throws Exception {
System.out.println("[接口InitializingBean.afterPropertiesSet() ]");
} @Override
public void setBeanName(String name) {
System.out.println("[接口BeanNameAware.setBeanName() ]");
} @Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("[接口BeanFactoryAware.setBeanFactory() ]");
} public void myInit(){
System.out.println("[init-method]调用<bean>的init-method属性指定的初始化方法");
} public void myDestory() {
System.out.println("[destroy-method]调用<bean>的destroy-method属性指定的销毁方法");
} }
2.自定义工厂后处理器,复写postProcessBeanFactory方法,获取bean定义后添加属性mobile=110
package spring.ioc; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; /**
*
* @ClassName:MyBeanFactoryPostProcessor
* @Description:自定义工厂后处理器
* @author diandian.zhang
* @date 2017年10月25日下午7:14:09
*/
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public MyBeanFactoryPostProcessor() {
super();
System.out.println("[MyBeanFactoryPostProcessor工厂后处理器]BeanFactoryPostProcessor实现类构造器!!");
} @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
throws BeansException {
System.out.println("[MyBeanFactoryPostProcessor工厂后处理器]BeanFactoryPostProcessor.postProcessBeanFactory()获取bean定义后添加属性mobile=110");
BeanDefinition bd = arg0.getBeanDefinition("person");
bd.getPropertyValues().addPropertyValue("mobile", "110");
} }
3.自定义Bean后处理器,复写postProcessBeforeInitialization和postProcessAfterInitialization2个方法,分别对应初始化前后时的操作。
package spring.ioc; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor; /**
*
* @ClassName:MyBeanPostProcessor
* @Description:自定义Bean后处理器
* @author diandian.zhang
* @date 2017年10月25日下午7:03:53
*/
public class MyBeanPostProcessor implements BeanPostProcessor { public MyBeanPostProcessor() {
super();
System.out.println("这是BeanPostProcessor实现类构造器!!");
} /**
*
* @Description 初始化前,处理器
* @param bean
* @param beanName
* @return
* @throws BeansException
* @author diandian.zhang
* @date 2017年10月25日下午7:07:02
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!beanName="+beanName);
return bean;
} /**
*
* @Description 初始化后,处理器
* @param bean
* @param beanName
* @return
* @throws BeansException
* @author diandian.zhang
* @date 2017年10月25日下午7:07:07
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!beanName="+beanName);
return bean;//注意,如果返回null,后续BeanPostProcessor不会再执行
} }
4.自定义实例化bean后处理器适配器,复写postProcessBeforeInstantiation、postProcessBeforeInstantiation、postProcessPropertyValues分别对应实例化Bean前调用、实例化Bean后调用、设置某个属性时调用
注意:InstantiationAwareBeanPostProcessorAdapter ,这里是实例化Instantiation,不是初始化Initialization!!!
package spring.ioc; import java.beans.PropertyDescriptor; import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; /**
*
* @ClassName:MyInstantiationAwareBeanPostProcessor
* @Description:BeanPostProcessor的子类,增加了更多自定方法
* @author diandian.zhang
* @date 2017年10月25日下午7:09:15
*/
public class MyInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter { public MyInstantiationAwareBeanPostProcessor() {
super();
System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");
} // 接口方法、实例化Bean之前调用
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass,String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法[实例化Bean之前调用 ]beanname="+beanName);
return null;
} // 接口方法、实例化Bean之后调用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out .println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法[实例化Bean之后调用]beanname="+beanName);
return bean;
} // 接口方法、设置某个属性时调用
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法 pvs="+pvs+",beanName="+beanName);
return pvs;
}
}
5.测试类,使用ClassPathXmlApplicationContext从xml中读取bean配置文件生成applicationContext容器应用上下文,这一步对应容器初始化。第二部从应用上下文中获取bean。最后一步注册一个关闭钩子,在容器关闭时触发。
package spring.ioc; import org.junit.Test; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import spring.aop.xml.dao.Dao; /**
*
* @ClassName:IOCTest
* @Description:测试类
* @author diandian.zhang
* @date 2017年10月25日下午4:42:01
*/
public class IOCTest { @Test
public void iocPersonTest(){
System.out.println("=============容器初始化======start=========");
@SuppressWarnings("resource")
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("simple_spring_bean.xml");//源码入口
System.out.println("=============容器初始化=======end========");
System.out.println("=============获取person bean====start=======");
Person person = applicationContext.getBean("person",Person.class);//获取Bean
System.out.println("=============获取person bean====end=======,person类名="+person.getClass().getName());
System.out.println("=============注册关闭钩子,关闭容器(JVM shutdown)时触发钩子!================");
((ClassPathXmlApplicationContext)applicationContext).registerShutdownHook();
}
}
直接运行,结果如下:
=============容器初始化======start=========
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
[MyBeanFactoryPostProcessor工厂后处理器]BeanFactoryPostProcessor实现类构造器!!
[MyBeanFactoryPostProcessor工厂后处理器]BeanFactoryPostProcessor.postProcessBeanFactory()获取bean定义后添加属性mobile=110
这是BeanPostProcessor实现类构造器!!
这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!
InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法[实例化Bean之前调用 ]beanname=person
[构造器] 调用Person的构造器实例化
InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法 pvs=PropertyValues: length=2; bean property 'mobile'; bean property 'name',beanName=person
[属性注入] mobile=110
[属性注入] name=张三
[接口BeanNameAware.setBeanName() ]
[接口BeanFactoryAware.setBeanFactory() ]
BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!beanName=person
[接口InitializingBean.afterPropertiesSet() ]
[init-method]调用<bean>的init-method属性指定的初始化方法
BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!beanName=person
InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法[实例化Bean之后调用]beanname=person
=============容器初始化=======end========
=============获取person bean====start=======
=============获取person bean====end=======,person类名=spring.ioc.Person
=============注册关闭钩子,关闭容器(JVM shutdown)时触发钩子!================
[接口DisposableBean.destroy() ]
[destroy-method]调用<bean>的destroy-method属性指定的销毁方法
总结流程:

====================================
参考
1.JDK8源码
2.全文参考:Spring Bean的生命周期(非常详细),
Spring bean 生命周期验证的更多相关文章
- spring bean 生命周期和 ? 作用域? spirng bean 相互依赖? jvm oom ? jvm 监控工具? ThreadLocal 原理
1. spring bean 生命周期 1. 实例化一个bean ,即new 2. 初始化bean 的属性 3. 如果实现接口 BeanNameAware ,调用 setBeanName 4. Bea ...
- Spring点滴四:Spring Bean生命周期
Spring Bean 生命周期示意图: 了解Spring的生命周期非常重要,我们可以利用Spring机制来定制Bean的实例化过程. -------------------------------- ...
- Spring Bean 生命周期之destroy——终极信仰
上一篇文章 Spring Bean 生命周期之我从哪里来 说明了我是谁? 和 我从哪里来? 的两大哲学问题,今天我们要讨论一下终极哲学我要到哪里去? 初始化 Spring Bean 有三种方式: @P ...
- 常见问题:Web/Servlet生命周期与Spring Bean生命周期
Servlet生命周期 init()初始化阶段 Servlet容器加载Servlet(web.xml中有load-on-startup=1;Servlet容器启动后用户首次向Servlet发请求;Se ...
- 大厂高频面试题Spring Bean生命周期最详解
Spring作为当前Java最流行.最强大的轻量级框架.Spring Bean的生命周期也是面试高频题,了解Spring Bean周期也能更好地帮助我们解决日常开发中的问题.程序员应该都知道Sprin ...
- Spring Bean生命周期,好像人的一生。。
大家好,我是老三,上节我们手撸了一个简单的IOC容器五分钟,手撸一个Spring容器!,这节我们来看一看Spring中Bean的生命周期,我发现,和人的一生真的很像. 简单说说IoC和Bean IoC ...
- 睡前聊一聊"spring bean 生命周期"
spring bean 生命周期=实属初销+2个常见接口+3个Aware型接口+2个生命周期接口 实属初销:spring bean生命周期只有四个阶段,即实例化->属性赋值->初始化-&g ...
- Spring Boot 启动源码解析结合Spring Bean生命周期分析
转载请注明出处: 1.SpringBoot 源码执行流程图 2. 创建SpringApplication 应用,在构造函数中推断启动应用类型,并进行spring boot自动装配 public sta ...
- Spring Bean 生命周期2
在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一个实例,而不是每次都产生一个新的对象使用Sin ...
随机推荐
- 201521123042《Java程序设计》第13周学习总结
本次作业参考文件 正则表达式参考资料 1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.bai ...
- 201521123085《Java程序设计》第10周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 finally 题目4-2 1.1 截图你的提交结果(出现学 ...
- 201521123090《Java程序设计》第10周学习总结
本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 书面作业 本次PTA作业题集异常.多线程 finally 题目4-2 1.1 截图你的提交结果(出现学号) 1.2 ...
- JVM(三)内存回收(一)
最近花了相当长一段时间在看Hotspot JVM的GC和内存分配,本节先总结和回顾一下内存回收的相关知识点,内存的分配放到下节再讨论. 一.什么是JVM的GC GC即Garbage Collectio ...
- Django中的信号及其用法
Django中提供了"信号调度",用于在框架执行操作时解耦. 一些动作发生的时候,系统会根据信号定义的函数执行相应的操作 Django中内置的signal Model_signal ...
- Chrome控制台选择器简介
Chrome的控制台是支持用$来获取元素的,这点可能是很多人不知道的.本篇文章将会简单介绍怎样更好的来使用这种快捷方式来获取元素. 判断当前窗口的$是来自谁的 我们知道jQ里面经常使用$来进行元素选择 ...
- php多态
多态性是指相同的操作或函数.过程可作用于多种类型的对象上并获得不同的结果.不同的对象,收到同一消息将可以产生不同的结果,这种现象称为多态性. 多态性允许每个对象以适合自身的方式去响应共同的消息.多态性 ...
- Redis介绍——Linux环境Redis安装全过程和遇到的问题及解决方案
一:redis的入门介绍: 首先贴出官网; 英文:https://redis.io/ 中文:http://www.redis.cn/ 1.是什么 --REmote DIctionary Server( ...
- Java钉钉开发_02_免登授权(身份验证)(附源码)
源码已上传GitHub: https://github.com/shirayner/DingTalk_Demo 一.本节要点 1.免登授权的流程 (1)签名校验 (2)获取code,并传到后台 (3) ...
- Docker入门之四搭建私有仓库
前面学习了下镜像和容器,今天来学习下仓库,来搭建本地私有仓库.当然可以使用远程的共有的仓库,但在企业中有的还是放在本地,所以需要搭建私有仓库. 一.搭建仓库 可以在容器中run一个仓库镜像. dock ...