Spring Bean Life Cycle

When container starts – a Spring bean needs to be instantiated, based on Java or XML bean definition. It may also be required to perform some post-initialization steps to get it into a usable state. Same bean life cycle is for spring boot applications as well.

前言

    Spring Bean的生命周期只有这四个阶段。把这四个阶段和每个阶段对应的扩展点糅合在一起虽然没有问题,但是这样非常凌乱,难以记忆。要彻底搞清楚Spring的生命周期,首先要把这四个阶段牢牢记住。实例化和属性赋值对应构造方法和setter方法的注入,初始化和销毁是用户能自定义扩展的两个阶段。在这四步之间穿插的各种扩展点。

Bean 四个阶段:

1).实例化 Instantiation
2).属性赋值 Populate
3).初始化 Initialization
4).销毁 Destruction

实例化 -> 属性赋值 -> 初始化 -> 销毁

Bean 的生命周期图示:


Bean的生命周期

准备对象:

UserLifeCycleTest-启动容器

1
2
3
4
5
6
7
8
9
10
public class UserLifeCycleTest {

public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("lifecycle.xml");
User user = applicationContext.getBean(User.class);
System.out.println(user);
//关闭IOC容器
applicationContext.close();
}
}

User-实体类:

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
public class User implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {

private String name;
private int age;

public User() {
this.name = "laowang";
this.age = 18;
System.out.println("======== User Constructor ========");
}

public User(String name, int age) {
this.name = name;
this.age = age;
System.out.println("======== User Constructor [name]" + name + " [age]" + age + " ========");
}

@Override
public void setBeanName(String name) {
System.out.println("======== User setBeanName【" + name + "】 ========");
}

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("======== User setBeanFactory【" + beanFactory + "】invoke ========");
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("======== User setApplicationContext【" + applicationContext + "】invoke ========");
}

//======== BeforeInitialization ========

@PostConstruct
public void postConstruct() {
System.out.println("======== User postConstruct ========");
}

@Override
public void afterPropertiesSet() throws Exception {
System.out.println("======== User afterPropertiesSet ========");
}

public void initMethod() {
System.out.println("======== User initMethod ========");
}

//======== AfterInitialization ========

@PreDestroy
public void PreDestroy() {
System.out.println("======== User PreDestroy ========");
}

@Override
public void destroy() throws Exception {
System.out.println("======== User destroy ========");
}

public void destroyMethod() {
System.out.println("======== User destroyMethod ========");
}


//-------------------getter,setter,toString start---------------

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

//-------------------getter,setter,toString end---------------

UserInstantiationAwareBeanPostProcessor-User处理类:

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
public class UserInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanClass.equals(User.class)) {
System.out.println("======== BeforeInstantiation beanClass【" + beanClass + "】" + "beanName【" + beanName + "】========");
}
return null;
}

@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (bean instanceof User) {
System.out.println("======== AfterInstantiation bean【" + bean + "】" + "beanName【" + beanName + "】========");
}
return true;
}

@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
if (bean instanceof User) {
System.out.println("======== PropertyValues【" + pvs + "】 PropertyDescriptor 【" + pds + "】 bean【" + bean + "】" + "beanName【" + beanName + "】========");
}
return pvs;
}


//----------------------------------以下是 BeanPostProcessor的方法 ----------------------------------

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof User) {
System.out.println("======== BeforeInitialization bean【" + bean + "】" + "beanName【" + beanName + "】========");
}
return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof User) {
System.out.println("======== AfterInitialization bean【" + bean + "】" + "beanName【" + beanName + "】========");
}
return bean;
}
}

lifecycle.xml配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<context:annotation-config />
y
<bean id="user" class="com.arsenal.beanlifecycle.User" init-method="initMethod" destroy-method="destroyMethod"/>

<bean id="userInstantiationAwareBeanPostProcessor"
class="com.arsenal..UserInstantiationAwareBeanPostProcessor"/>

</beans>

执行顺序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
======== BeforeInstantiation beanClass【class com.arsenal.beanlifecycle.UserbeanNameuser========
======== User Constructor ========
======== AfterInstantiation bean【com.arsenal.beanlifecycle.User@1b083826】beanName【user】========
======== PropertyValues【PropertyValues: length=0】 PropertyDescriptor 【[Ljava.beans.PropertyDescriptor;@105fece7】 bean【com.arsenal.beanlifecycle.User@1b083826】beanName【user】========
======== User setBeanName【user】 ========
======== User setBeanFactory【org.springframework.beans.factory.support.DefaultListableBeanFactory@184f6be2: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,user,userInstantiationAwareBeanPostProcessor]; root of factory hierarchy】invoke ========
======== User setApplicationContext【org.springframework.context.support.ClassPathXmlApplicationContext@7dc36524: startup date [Sun Sep 20 16:16:22 CST 2020]; root of context hierarchy】invoke ========
======== BeforeInitialization bean【com.arsenal.beanlifecycle.User@1b083826】beanName【user】========
======== User postConstruct ========
======== User afterPropertiesSet ========
======== User initMethod ========
======== AfterInitialization bean【com.arsenal.beanlifecycle.User@1b083826】beanName【user】========
======== User PreDestroy ========
======== User destroy ========
======== User destroyMethod ========

执行详细信息:

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
16:16:22.858 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'
16:16:22.858 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'user'
======== BeforeInstantiation beanClass【class com.arsenal.beanlifecycle.UserbeanNameuser========
======== User Constructor ========
16:16:22.860 [main] DEBUG org.springframework.context.annotation.CommonAnnotationBeanPostProcessor - Found init method on class [com.arsenal.beanlifecycle.User]: public void com.arsenal.beanlifecycle.User.postConstruct()
16:16:22.860 [main] DEBUG org.springframework.context.annotation.CommonAnnotationBeanPostProcessor - Found destroy method on class [com.arsenal.beanlifecycle.User]: public void com.arsenal.beanlifecycle.User.PreDestroy()
16:16:22.860 [main] DEBUG org.springframework.context.annotation.CommonAnnotationBeanPostProcessor - Registered init method on class [com.arsenal.beanlifecycle.User]: org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement@a1ab9f17
16:16:22.860 [main] DEBUG org.springframework.context.annotation.CommonAnnotationBeanPostProcessor - Registered destroy method on class [com.arsenal.beanlifecycle.User]: org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement@194fb3f7
16:16:22.860 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Eagerly caching bean 'user' to allow for resolving potential circular references
======== AfterInstantiation bean【com.arsenal.beanlifecycle.User@1b083826】beanName【user】========
======== PropertyValues【PropertyValues: length=0】 PropertyDescriptor 【[Ljava.beans.PropertyDescriptor;@105fece7】 bean【com.arsenal.beanlifecycle.User@1b083826】beanName【user】========
======== User setBeanName【user】 ========
======== User setBeanFactory【org.springframework.beans.factory.support.DefaultListableBeanFactory@184f6be2: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,user,userInstantiationAwareBeanPostProcessor]; root of factory hierarchy】invoke ========
======== User setApplicationContext【org.springframework.context.support.ClassPathXmlApplicationContext@7dc36524: startup date [Sun Sep 20 16:16:22 CST 2020]; root of context hierarchy】invoke ========
======== BeforeInitialization bean【com.arsenal.beanlifecycle.User@1b083826】beanName【user】========
16:16:22.864 [main] DEBUG org.springframework.context.annotation.CommonAnnotationBeanPostProcessor - Invoking init method on bean 'user': public void com.arsenal.beanlifecycle.User.postConstruct()
======== User postConstruct ========
16:16:22.864 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'user'
======== User afterPropertiesSet ========
16:16:22.864 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking init method 'initMethod' on bean with name 'user'
======== User initMethod ========
======== AfterInitialization bean【com.arsenal.beanlifecycle.User@1b083826】beanName【user】========
16:16:22.864 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Finished creating instance of bean 'user'
16:16:22.864 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'userInstantiationAwareBeanPostProcessor'
16:16:22.865 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
16:16:22.881 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@3ee0fea4]
16:16:22.882 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
16:16:22.885 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
16:16:22.888 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'user'
com.arsenal.beanlifecycle.User@1b083826
16:16:22.888 [main] INFO org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@7dc36524: startup date [Sun Sep 20 16:16:22 CST 2020]; root of context hierarchy
16:16:22.888 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
16:16:22.889 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@184f6be2: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,user,userInstantiationAwareBeanPostProcessor]; root of factory hierarchy
16:16:22.889 [main] DEBUG org.springframework.context.annotation.CommonAnnotationBeanPostProcessor - Invoking destroy method on bean 'user': public void com.arsenal.beanlifecycle.User.PreDestroy()
======== User PreDestroy ========
16:16:22.889 [main] DEBUG org.springframework.beans.factory.support.DisposableBeanAdapter - Invoking destroy() on bean with name 'user'
======== User destroy ========
16:16:22.890 [main] DEBUG org.springframework.beans.factory.support.DisposableBeanAdapter - Invoking destroy method 'destroyMethod' on bean with name 'user'
======== User destroyMethod ========

延伸

    雷丰阳_spring源码
    SpringIoc 实现原理
    spring-bean-life-cycle
    Spring Bean的生命周期
    深究Spring中Bean的生命周期

Content
  1. 1. 前言
  2. 2. Bean的生命周期
  3. 3. 延伸