觉得不错请按下图操作,掘友们,哈哈哈!!!
一:简述以及目录
Bean 的⽣命周期平常可能我们没太多去了解,但是在面试的时候这也是一个老生常谈的问题。
二:呕心沥血的流程图,绝对肝货
2.1 简化版
2.2 详细版
三:基础概念扫盲
2.1 什么是IOC
IOC全称是Inversion of Control,控制反转。它属于一种设计思想,由容器将设计好的对象交给容器控制,而非对象内部直接new。
四:执行流程分析
4.1 测试demo
package com.xiao.ma.yi;
import lombok.ToString;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
public class XiaoMaYLifeBean implements InitializingBean, BeanFactoryAware, BeanNameAware, DisposableBean {
/**
* 姓名
*/
private String name;
public XiaoMaYLifeBean() {
System.out.println("1.调用构造方法: 早上好呀 我是一只快乐的小蚂蚁!");
}
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方法:咯吱咯吱吃东西!!");
}
@Override
public void destroy() throws Exception {
System.out.println("9.DisposableBean#destroy方法:晒晒太阳,准备回家了");
}
public void destroyMethod() {
System.out.println("10.自定义destroy方法:跑了一天好累,要休息了哦 !!!");
}
public void go(){
System.out.println("XiaoMaYLifeBean:生活不就这样吗???");
}
}
同时自定义一个处理器:
package com.xiao.ma.yi;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class XiaoMaYiLifePostProcessor 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;
}
}
XML配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress ALL -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!--打开@Autowired等注解-->
<context:annotation-config/>
<context:component-scan base-package="com" />
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean name="myBeanPostProcessor" class="com.xiao.ma.yi.XiaoMaYiLifePostProcessor" />
<bean name="xiaoMaYLifeBean" class="com.xiao.ma.yi.XiaoMaYLifeBean"
init-method="init" destroy-method="destroyMethod">
<property name="name" value="快乐小蚂蚁" />
</bean>
</beans>
测试执行入口:
import com.xiao.ma.yi.XiaoMaYLifeBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) throws Exception {
ApplicationContext context =new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
XiaoMaYLifeBean xiaoMaYLifeBean = (XiaoMaYLifeBean) context.getBean("xiaoMaYLifeBean");
xiaoMaYLifeBean.go();
((ClassPathXmlApplicationContext) context) .close();
}
}
整个执行的结果如下:
- 1.调用构造方法: 早上好呀 我是一只快乐的小蚂蚁!
- 2.设置属性:我的名字叫快乐小蚂蚁
- 3.调用BeanNameAware#setBeanName方法: 我要起床了!!!
- 4.调用BeanFactoryAware#setBeanFactory方法:我穿好衣服了
- 5.BeanPostProcessor.postProcessBeforeInitialization方法:准备出门
- 6.InitializingBean#afterPropertiesSet方法:费了好大力气,找到了一块好吃的
- 7.自定义init方法:咯吱咯吱吃东西!!
- 8.BeanPostProcessor#postProcessAfterInitialization方法:终于吃饱了!
- XiaoMaYLifeBean:生活不就这样吗???
- 9.DisposableBean#destroy方法:晒晒太阳,准备回家了
- 10.自定义destroy方法:跑了一天好累,要休息了哦 !!!
是不是看到这里就很明显了,和前边Bean ⽣命周期流程图相互应。
4.2 我们能使用的扩展⽅法
通过上边我们可以以发现,在bean的整个声明周期中,我们在不同的时机可以进行拓展,基本上⼤致可以分为 4 类:
- 实现Aware 接⼝:让 我们的Bean 能拿到容器的⼀些资源,例如实现 BeanNameAware 的 setBeanName() 设置bean的名称, 实现BeanFactoryAware 的 setBeanFactory() 设置bean的工厂;
- 添加一些我们自定义的后处理器:进⾏⼀些前置和后置的处理,例如 BeanPostProcessor 的 postProcessBeforeInitialization() 和 postProcessAfterInitialization()在初始化前后做一些我们想要的操作;
- ⽣命周期接⼝:定义初始化⽅法和销毁⽅法的,例如 InitializingBean 的 afterPropertiesSet(),以及 DisposableBean 的 destroy();
- 配置⽣命周期⽅法:可以通过配置⽂件,或者configuration方式,⾃定义初始化和销毁⽅法,例如配置⽂件配置的 init() 和 destroyMethod()。
五:深入源码
5.1 代码入口
这里我们说的入口其实就是 AbstractApplicationContext#refresh 方法,这里主要列举我们bean声明周期中主要的点:
因为有一些系统bean也是通过这种方式创建,如上图,这里边有八个,所以这个地方,我们要把这些系统bean跳过去,找到我们的目标bean->XiaoMaYLifeBean.class
图中就到了我们自己定义的bean了,进入getBean() 方法。
进⼊ doGetBean(),从 getSingleton() 没有找到对象,进⼊创建 Bean 的逻辑。
开始创建XiaoMaYLifeBean 对象
进入createBean()方法:
5.2 bean的实例化
进⼊ doCreateBean() 后,我们走到 createBeanInstance() 调用处:
进入createBeanInstance() 方法:
接着进入instantiateBean() 方法:
进入instantiate() 方法:
进入BeanUtils.instantiateClass() 方法:
进入构造函数newInstance() 方法:
进入到XiaoMaYLifeBean的无参构造函数中:
到这里我们的bean就被实例化出来了,但是属性什么的还没填充,我们继续走回到: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean中:
5.3 填充bean,属性赋值
进入populateBean()方法:
进⼊ populateBean() 后,执⾏ applyPropertyValues()
进⼊ applyPropertyValues(),执⾏ bw.setPropertyValues()
进⼊ processLocalProperty(),执⾏ ph.setValue()。
进入setValue() 方法:
进入invoke() 方法:
这时候就进入了我们自定义类的属性set方法:
到这⾥,populateBean() 就执⾏完毕,下⾯开始初始化 Bean。
5.4 初始化bean
这时候又回到了我们:AbstractAutowireCapableBeanFactory#doCreateBean,此时执行到了initializeBean()方法位置:
进入initializeBean()方法:
进入invokeAwareMethods()方法:
进入我们自己类设置beanName的方法:
回到 invokeAwareMethods():
进入我们自己类设置beanFactory的方法:
第一次回到 initializeBean(),执⾏下⾯逻辑。进入:applyBeanPostProcessorsBeforeInitialization() 方法:
找到我们的处理器:
执行我们自定义处理器的postProcessBeforeInitialization方法
第⼆次回到 initializeBean(),执⾏下⾯逻辑。
进入invokeInitMethods() 方法:
⾛进示例 XiaoMaYLifeBean 的⽅法,执⾏ afterPropertiesSet()。
返回 invokeInitMethods(),执⾏下⾯逻辑。
⾛进示例 XiaoMaYLifeBean 的⽅法,执⾏ init()。
第三次回到 initializeBean(),执⾏下⾯逻辑。
进入applyBeanPostProcessorsAfterInitialization()方法:
执行我们我们⾃⼰定义的后置处理⽅法postProcessAfterInitialization():
目前到这⾥,XiaoMaYLifeBean初始化的流程全部结束,其实主要流程都是围绕 initializeBean() 展开的。
六:bean的销毁
当 XiaoMaYLifeBean ⽣成后,后⾯就开始执⾏销毁操作,销毁的流程就⽐较简单。
入口close() 方法:
进入close() 方法:
进入doClose() 方法,看到我们标注的点:
这里就可以看到我们自己的close() 方法了:
⾛进示例 XiaoMaYLifeBean 的⽅法,执⾏ destroy()。
回到 destroy()方法,执⾏下⾯逻辑。
进入invokeCustomDestroyMethod() 方法:
结果完整出来了:
七:总要有总结
我们再回顾⼀下⼏个重要的⽅法:
- doCreateBean():这个是创建bean⼊⼝;
- createBeanInstance():就如方法名一样是⽤来初始化 Bean,⾥⾯会调⽤对象的构造⽅法,上边源码调试流程我们也有涉及;
- populateBean():填充对象属性依赖,以及成员变量初始化;
- initializeBean():这⾥⾯包含了 4 个⽅法,
- 先执⾏ aware 的 BeanNameAware比如设置beanName、BeanFactoryAware 接⼝ 设置beanFactory;
- 再执⾏ BeanPostProcessor bean的前置处理器接口;
- 然后执⾏ InitializingBean 接⼝,自己实现的 init()方法;
- 最后执⾏ BeanPostProcessor 的后置处理器接口。
- destory():先执⾏ DisposableBean 接⼝,再执⾏配置的 destroyMethod()。
相信通过这一篇bean的生命周期,我们对Springbean的生命周期有更深入的了解,其实里边也包含了AOP,以及循环依赖的相关东西了,在这个过程中其实对于我们无论是日常Spring相关的问题,还是面试时候的一些问题,如果熟读了一遍我相信很多都会在其中找到答案的。
整个系列目录:
本文正在参加「金石计划」