Spring源码解析-老生常谈Bean ⽣命周期 ,但这个你

觉得不错请按下图操作,掘友们,哈哈哈!!!

image.png

一:简述以及目录

Bean 的⽣命周期平常可能我们没太多去了解,但是在面试的时候这也是一个老生常谈的问题。

image.png

二:呕心沥血的流程图,绝对肝货

2.1 简化版

image.png

2.2 详细版

bean的创建过程1.png

三:基础概念扫盲

2.1 什么是IOC

Spring IOC1.png

IOC全称是Inversion of Control,控制反转。它属于一种设计思想,由容器将设计好的对象交给容器控制,而非对象内部直接new。

四:执行流程分析

4.1 测试demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
csharp复制代码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:生活不就这样吗???");
}
}

同时自定义一个处理器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
typescript复制代码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配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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>

测试执行入口:

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码
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声明周期中主要的点:

image.png

image.png

image.png

image.png

因为有一些系统bean也是通过这种方式创建,如上图,这里边有八个,所以这个地方,我们要把这些系统bean跳过去,找到我们的目标bean->XiaoMaYLifeBean.class

image.png

图中就到了我们自己定义的bean了,进入getBean() 方法。

image.png

进⼊ doGetBean(),从 getSingleton() 没有找到对象,进⼊创建 Bean 的逻辑。

image.png

开始创建XiaoMaYLifeBean 对象
image.png

进入createBean()方法:

image.png

5.2 bean的实例化

进⼊ doCreateBean() 后,我们走到 createBeanInstance() 调用处:

image.png

进入createBeanInstance() 方法:

image.png

接着进入instantiateBean() 方法:

image.png

进入instantiate() 方法:

image.png

进入BeanUtils.instantiateClass() 方法:

image.png

进入构造函数newInstance() 方法:
image.png

进入到XiaoMaYLifeBean的无参构造函数中:

image.png

到这里我们的bean就被实例化出来了,但是属性什么的还没填充,我们继续走回到:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean中:

5.3 填充bean,属性赋值

image.png

进入populateBean()方法:

image.png

进⼊ populateBean() 后,执⾏ applyPropertyValues()

image.png
进⼊ applyPropertyValues(),执⾏ bw.setPropertyValues()

image.png

image.png

image.png

image.png

image.png

进⼊ processLocalProperty(),执⾏ ph.setValue()。
image.png

进入setValue() 方法:
image.png

进入invoke() 方法:

image.png

这时候就进入了我们自定义类的属性set方法:

image.png

到这⾥,populateBean() 就执⾏完毕,下⾯开始初始化 Bean。

5.4 初始化bean

这时候又回到了我们:AbstractAutowireCapableBeanFactory#doCreateBean,此时执行到了initializeBean()方法位置:

image.png

进入initializeBean()方法:

image.png

进入invokeAwareMethods()方法:

image.png

进入我们自己类设置beanName的方法:

image.png

回到 invokeAwareMethods():

image.png

进入我们自己类设置beanFactory的方法:

image.png

第一次回到 initializeBean(),执⾏下⾯逻辑。进入:applyBeanPostProcessorsBeforeInitialization() 方法:

image.png

找到我们的处理器:

image.png

执行我们自定义处理器的postProcessBeforeInitialization方法

image.png

image.png

第⼆次回到 initializeBean(),执⾏下⾯逻辑。

进入invokeInitMethods() 方法:

image.png

image.png

⾛进示例 XiaoMaYLifeBean 的⽅法,执⾏ afterPropertiesSet()。

image.png

返回 invokeInitMethods(),执⾏下⾯逻辑。

image.png

image.png
⾛进示例 XiaoMaYLifeBean 的⽅法,执⾏ init()。

image.png

第三次回到 initializeBean(),执⾏下⾯逻辑。

image.png

进入applyBeanPostProcessorsAfterInitialization()方法:

image.png

执行我们我们⾃⼰定义的后置处理⽅法postProcessAfterInitialization():

image.png

目前到这⾥,XiaoMaYLifeBean初始化的流程全部结束,其实主要流程都是围绕 initializeBean() 展开的。

六:bean的销毁

当 XiaoMaYLifeBean ⽣成后,后⾯就开始执⾏销毁操作,销毁的流程就⽐较简单。
入口close() 方法:
image.png

进入close() 方法:

image.png

进入doClose() 方法,看到我们标注的点:

image.png

image.png

image.png

image.png

image.png

image.png

image.png
这里就可以看到我们自己的close() 方法了:

image.png

⾛进示例 XiaoMaYLifeBean 的⽅法,执⾏ destroy()。

image.png

回到 destroy()方法,执⾏下⾯逻辑。

image.png

进入invokeCustomDestroyMethod() 方法:

image.png

image.png

结果完整出来了:

image.png

七:总要有总结

我们再回顾⼀下⼏个重要的⽅法:

  • doCreateBean():这个是创建bean⼊⼝;
  • createBeanInstance():就如方法名一样是⽤来初始化 Bean,⾥⾯会调⽤对象的构造⽅法,上边源码调试流程我们也有涉及;
  • populateBean():填充对象属性依赖,以及成员变量初始化;
  • initializeBean():这⾥⾯包含了 4 个⽅法,
    • 先执⾏ aware 的 BeanNameAware比如设置beanName、BeanFactoryAware 接⼝ 设置beanFactory;
    • 再执⾏ BeanPostProcessor bean的前置处理器接口;
    • 然后执⾏ InitializingBean 接⼝,自己实现的 init()方法;
    • 最后执⾏ BeanPostProcessor 的后置处理器接口。
  • destory():先执⾏ DisposableBean 接⼝,再执⾏配置的 destroyMethod()。

相信通过这一篇bean的生命周期,我们对Springbean的生命周期有更深入的了解,其实里边也包含了AOP,以及循环依赖的相关东西了,在这个过程中其实对于我们无论是日常Spring相关的问题,还是面试时候的一些问题,如果熟读了一遍我相信很多都会在其中找到答案的。

整个系列目录:

Spring 源码解析-从源码角度看bean的循环依赖

本文正在参加「金石计划」

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%