SpringBean的生命周期

  Spring中Bean的创建是经过了很多的步骤,并且也提供了一些方法,方便在创建过程中获取或执行一些逻辑,完成一下自定义的操作。
  我们可以通过这些方法来查看Bean的生命周期。

示例

首先创建一个普通的maven项目,引入spring相关依赖:

1
2
3
4
5
6
7
8
9
10
11
12
<!--引入Spring IoC容器功能-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>

<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>

接下来创建一个Result类,以它来查看Bean的加载流程:

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
60
61
62
63
64
65
66
67
public class Result implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {

private String message;
private Integer code;

@Autowired
private Data data;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public Integer getCode() {
return code;
}

public void setCode(Integer code) {
this.code = code;
}

public void initMethod() {
System.out.println("基于XML的init-method属性的方法,开始执行......");
}

@PostConstruct
public void postConstruct() {
System.out.println("基于postConstruct注解的方法开始执行......");
}

@Override
public void setBeanName(String name) {
System.out.println("BeanNameAware ====> 注册我成为bean时定义的id:" + name);
}

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryAware ===> 管理我的bean factory为:" + beanFactory);
}

@Override
public void destroy() throws Exception {
System.out.println("DisposableBean ====> destroy方法开始执行.....");
}

@PreDestroy
public void PreDestroy(){
System.out.println("基于PreDestroy注解的方法开始执行......");
}

public void destroyMethod() {
System.out.println("基于destroy-method标签属性的方法,开始执行......");
}

@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean ====> afterPropertiesSet 开始执行......");
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("ApplicationContextAware ====> 高级容器接口ApplicationContext:" + applicationContext);
}
}

其中依赖的Data类,用来测试属性注入。
接下来需要创建配置文件applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
">

<!--开启注解扫描,base-package指定扫描的包路径-->
<context:component-scan base-package="com.lfj.demo"/>

<bean id="dataMsg" class="com.lfj.demo.pojo.Data" />
<bean id="demoResult" class="com.lfj.demo.pojo.Result" init-method="initMethod" destroy-method="destroyMethod" />

</beans>

其次,还需要定义一个MyBeanPostProcessor类,查看后置处理的执行顺序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if("demoResult".equalsIgnoreCase(beanName)) {
System.out.println("MyBeanPostProcessor ===> before方法拦截处理demoResult");
}
return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("demoResult".equalsIgnoreCase(beanName)) {
System.out.println("MyBeanPostProcessor ===> after方法拦截处理demoResult");
}
return bean;
}
}

然后进行执行测试:

1
2
3
4
5
6
7
8
@Test
public void testBeanLife(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
Object demoResult = applicationContext.getBean("demoResult");
System.out.println("创建完毕 ===>" + demoResult);
// 触发销毁
applicationContext.close();
}

查看执行结果如下所示:

img.png

且如果断点在第一行输出的位置,会发现自动注入的Data类已经赋值完成。

生命周期图

通过上面的程序,可以得到整个Bean的生命周期图如下所示:

img.png

Bean的生命周期如下:

  1. BeanFactory读取所有的Bean的属性,封装为BeanDefinition,如果有实现BeanFactoryPostProcessor接口,则执行postProcessBeanFactory()方法,对BeanDefinition进行修改;
    • 例如PropertyPlaceholderConfigurer,将配置中的占位符,用properties文件中的属性进行替换;
  2. 根据配置情况调⽤Bean构造⽅法⼯⼚⽅法实例化Bean;
  3. 根据配置或注解,将依赖的属性进行自动注入;
  4. 如果Bean实现了BeanNameAware接⼝,则Spring调⽤Bean的setBeanName()⽅法传⼊当前Bean的id值
  5. 如果Bean实现了BeanFactoryAware接⼝,则Spring调⽤setBeanFactory()⽅法传⼊当前⼯⼚实例的引⽤;
  6. 如果Bean实现了ApplicationContextAware接⼝,则Spring调⽤setApplicationContext()⽅法传⼊当前ApplicationContext实例的引⽤;
  7. 如果BeanPostProcessor和Bean关联,则Spring将调⽤该接⼝的预初始化⽅法postProcessBeforeInitialization()对Bean进⾏加⼯操作,此处⾮常重要,Spring的AOP就是利⽤它实现的
  8. 如果Bean中有使用了@PostConstruct注解的方法,则Spring会调用执行;
  9. 如果Bean实现了InitializingBean接⼝,则Spring将调⽤afterPropertiesSet()⽅法;
  10. 如果在配置⽂件中通过init-method属性指定了初始化⽅法,则调⽤该初始化⽅法;
  11. 如果BeanPostProcessor和Bean关联,则Spring将调⽤该接⼝的初始化⽅法postProcessAfterInitialization();
  12. 此时,Bean创建完成,已经可以被系统使⽤了。
    1. 如果在<bean>中指定了该Bean的作⽤范围为scope="singleton",则将该Bean放⼊Spring IoC的缓存池中,将触发Spring对该Bean的⽣命周期管理;
    2. 如果在<bean>中指定了该Bean的作⽤范围为scope="prototype",则将该Bean交给调⽤者,Spring不再管理;
  13. 对于单例的Bean的销毁过程如下:
    1. 如果Bean中有使用了@PreDestroy注解的方法,则Spring会调用执行对Bean进⾏销毁;
    2. 如果Bean实现了DisposableBean接⼝,则Spring会调⽤destroy()⽅法将Spring中的Bean销毁;
    3. 如果在配置⽂件中通过destory-method属性指定了Bean的销毁⽅法,则Spring将调⽤该⽅法对Bean进⾏销毁。