Spring Bean生命周期

Spring Bean生命周期

生命周期流程

首先看下生命周期图:

再来一张执行过程:

Spring Bean的生命周期只有四个阶段。要彻底搞清楚Spring的生命周期,首先要把这四个阶段牢牢记住。实例化和属性赋值对应构造方法setter方法的注入,初始化和销毁是用户能自定义扩展的两个阶段。在这四步之间穿插的各种扩展点。

  • 实例化 Instantiation

  • 属性赋值 Populate

  • 初始化 Initialization

  • 销毁 Destruction

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

主要逻辑都在doCreateBean()方法中,逻辑很清晰,就是顺序调用以下三个方法,这三个方法与三个生命周期阶段一一对应,非常重要,在后续扩展接口分析中也会涉及。

createBeanInstance() -> 实例化
populateBean() -> 属性赋值
initializeBean() -> 初始化

源码如下,能证明实例化,属性赋值和初始化这三个生命周期的存在。关于本文的Spring源码都将忽略无关部分,便于理解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 忽略了无关代码
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {

// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
// 实例化阶段!
instanceWrapper = createBeanInstance(beanName, mbd, args);
}

// Initialize the bean instance.
Object exposedObject = bean;
try {
// 属性赋值阶段!
populateBean(beanName, mbd, instanceWrapper);
// 初始化阶段!
exposedObject = initializeBean(beanName, exposedObject, mbd);
}

}

至于销毁,是在容器关闭时调用的,详见ConfigurableApplicationContext#close()

在谈生命周期之前有一点需要先明确:

Spring 只帮我们管理单例模式 Bean 的完整生命周期,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。

AOP扩展bean生命周期

Spring生命周期相关的常用切入方式非常多,主要有下列方式:

注解方式

在 bean 初始化时会经历几个阶段,首先可以使用注解 @PostConstruct, @PreDestroy 来在 bean 的创建和销毁阶段进行调用。

两个生命周期接口InitializingBean, DisposableBean

还可以实现 InitializingBean, DisposableBean 这两个接口,也是在初始化以及销毁阶段调用。实例化和属性赋值都是Spring帮助我们做的,能够自己实现的就只有 初始化销毁 两个生命周期阶段.

  • InitializingBean
    对应生命周期的初始化阶段,在源码的 invokeInitMethods(beanName, wrappedBean, mbd) 方法中调用。

    有一点需要注意,因为Aware方法都是执行在初始化方法之前,所以可以在初始化方法中放心大胆的使用Aware接口获取的资源,这也是我们自定义扩展Spring的常用方式。
    除了实现InitializingBean接口之外还能通过注解或者xml配置的方式指定初始化方法,至于这几种定义方式的调用顺序其实没有必要记。因为这几个方法对应的都是同一个生命周期,只是实现方式不同,我们一般只采用其中一种方式。

  • DisposableBean
    类似于InitializingBean,对应生命周期的销毁阶段,以ConfigurableApplicationContext#close() 方法作为入口,实现是通过循环取所有实现了DisposableBean接口的Bean然后调用其`destroy() 方法;

自定义初始化和销毁方法

也可以自定义方法用于在初始化、销毁阶段调用

实现 Aware 接口

Aware类型的接口的作用就是让我们能够拿到Spring容器中的一些资源。基本都能够见名知意,Aware之前的名字就是可以拿到什么资源,例如BeanNameAware可以拿到BeanName,以此类推。调用时机需要注意:所有的Aware方法都是在初始化阶段之前调用的!

Aware接口具体可以分为两组。如下排列顺序同样也是Aware接口的执行顺序:

  • Aware Group1

    BeanNameAware

    BeanClassLoaderAware

    BeanFactoryAware

  • Aware Group2

    EnvironmentAware

    EmbeddedValueResolverAware 实现该接口能够获取Spring EL解析器,用户的自定义注解需要支持spel表达式的时候可以使用,非常方便。

    ApplicationContextAware(ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware) 这几个接口可能让人有点懵,实际上这几个接口可以一起记,其返回值实质上都是当前的ApplicationContext对象,因为ApplicationContext是一个复合接口

1
2
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {}

这里涉及一道面试题,ApplicationContextBeanFactory的区别,可以从ApplicationContext 继承的这几个接口入手,除去 BeanFactory 相关的两个接口就是ApplicationContext独有的功能.

BeanPostProcessor, InstantiationAwareBeanPostProcessor接口

增强处理器(容器级别),实现 BeanPostProcessor 接口,Spring 中所有 bean 在做初始化时都会调用该接口中的两个方法,, 正因为如此,这些接口的功能非常强大,Spring内部扩展也经常使用这些接口,例如自动注入以及AOP的实现都和他们有关。

这是Spring扩展中最重要的两个接口!

  • InstantiationAwareBeanPostProcessor作用于实例化阶段的前后;

  • BeanPostProcessor作用于初始化阶段的前后;

  • InstantiationAwareBeanPostProcessor实际上继承了 BeanPostProcessor接口,严格意义上来看他们是两父子;

Aware调用时机源码分析

详情如下,忽略了部分无关代码。代码位置就是initializeBean方法详情,这也说明了Aware都是在初始化阶段之前调用的!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 见名知意,初始化阶段调用的方法
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {

// 这里调用的是Group1中的三个Bean开头的Aware
invokeAwareMethods(beanName, bean);

Object wrappedBean = bean;

// 这里调用的是Group2中的几个Aware,
// 而实质上这里就是前面所说的BeanPostProcessor的调用点!
// 也就是说与Group1中的Aware不同,这里是通过BeanPostProcessor(ApplicationContextAwareProcessor)实现的。
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
// 下文即将介绍的InitializingBean调用点
invokeInitMethods(beanName, wrappedBean, mbd);
// BeanPostProcessor的另一个调用点
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

return wrappedBean;
}

可以看到并不是所有的Aware接口都使用同样的方式调用。

  • Bean××Aware都是在代码中直接调用的;
  • ApplicationContext相关的Aware都是通过BeanPostProcessor#postProcessBeforeInitialization()实现的。

具体流程可以看一下 ApplicationContextAwareProcessor 这个类的源码,就是判断当前创建的Bean是否实现了相关的Aware方法,如果实现了会调用回调方法将资源传递给Bean。

至于Spring为什么这么实现,应该没什么特殊的考量。也许和Spring的版本升级有关。基于对修改关闭,对扩展开放的原则,Spring对一些新的Aware采用了扩展的方式添加。

BeanPostProcessor的调用时机也能在这里体现,包围住 invokeInitMethods 方法,也就说明了在初始化阶段的前后执行。

关于Aware接口的执行顺序,其实只需要记住第一组在第二组执行之前就行了.

实例Demo

User.java

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
/**
* @author Austin
* @since 2019/12/2 21:01 Mon
*/
public class User implements InitializingBean, DisposableBean, BeanNameAware, ApplicationContextAware,
BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware {

private ApplicationContext applicationContext;

private String username;

/**
* 自定义方法用于在初始化
*/
public void initMethod() {
System.out.println("调用Bean的函数(initMethod)");
}

@PostConstruct
public void postConstructor() {
System.out.println("调用Bean的函数(postConstruct)");
}

public User() {
System.out.println("调用Bean的函数(constructor)");
}

public void setUsername(String username) {
System.out.println("调用Bean的函数(setName/setAttribute)");
this.username = username;
}

@PreDestroy
public void preDestroy() {
System.out.println("调用Bean的函数(preDestroy)");
}

@Override
public void destroy() throws Exception {
System.out.println("调用Bean的函数(destroy())");
}

public void destroyMethod() {
System.out.println("调用Bean的函数(destroyMethod)");
}

@Override
public void afterPropertiesSet() throws Exception {
System.out.println("调用Bean的函数(afterPropertiesSet)");
}

@Override
public void setBeanName(String name) {
System.out.println("调用BeanNameAware的(setBeanName)函数");
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("调用ApplicationContextAware的(setApplicationContext)函数");
this.applicationContext = applicationContext;
}

@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("调用BeanClassLoaderAware的(setBeanClassLoader)函数");
}

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用BeanFactoryAware的(setBeanFactory)函数");
}

@Override
public void setEnvironment(Environment environment) {
System.out.println("调用EnvironmentAware的(setEnvironment)函数");
}
}

CustomBeanPostProcessor.java

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
/**
* @author Austin
* @since 2019/12/2 21:10 Mon
*/
@Component
public class CustomBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanPostProcessor {

/**
* 实例化之前调用
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanClass == User.class){
System.out.println("调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()函数");
}
return null;
}

/**
* 实例化之后调用
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (bean.getClass() == User.class){
System.out.println("调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation()函数");
}
return true;
}

/**
* 预初始化,初始化之前调用
*/
@Nullable
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean.getClass() == User.class) {
System.out.println("调用BeanPostProcessor的postProcessBeforeInitialization()函数");
}
return bean;
}

/**
* 后初始化 bean 初始化完成调用
*/
@Nullable
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean.getClass() == User.class) {
System.out.println("调用BeanPostProcessor的postProcessAfterInitialization()函数");
}
return bean;
}
}

BootStrap.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* @author Austin
* @since 2019/12/2 21:13 Mon
*/
@SpringBootApplication
public class BootStrap {

public static void main(String[] args) {
SpringApplication.run(BootStrap.class, args);
}

@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
public User user() {
User user = new User();
user.setUsername("xxxx");
return 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
调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()函数

调用Bean的函数(constructor)
调用Bean的函数(setName/setAttribute)

调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation()函数

调用BeanNameAware的(setBeanName)函数
调用BeanClassLoaderAware的(setBeanClassLoader)函数
调用BeanFactoryAware的(setBeanFactory)函数

调用EnvironmentAware的(setEnvironment)函数
调用ApplicationContextAware的(setApplicationContext)函数

调用BeanPostProcessor的postProcessBeforeInitialization()函数

调用Bean的函数(postConstruct)
调用Bean的函数(afterPropertiesSet)
调用Bean的函数(initMethod)

调用BeanPostProcessor的postProcessAfterInitialization()函数

调用Bean的函数(preDestroy)
调用Bean的函数(destroy())
调用Bean的函数(destroyMethod)

总结

Spring Bean的生命周期分为四个阶段多个扩展点。扩展点又可以分为影响多个Bean影响单个Bean。整理如下:

四个阶段

  • 实例化 Instantiation
  • 属性赋值 Populate
  • 初始化 Initialization
  • 销毁 Destruction

多个扩展点

  • 影响多个Bean

    • BeanPostProcessor
    • InstantiationAwareBeanPostProcessor
  • 影响单个Bean

    • Aware

      • Aware Group1

        • BeanNameAware
        • BeanClassLoaderAware
        • BeanFactoryAware
      • Aware Group2

        • EnvironmentAware
        • EmbeddedValueResolverAware
        • ApplicationContextAware (ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware)
    • 生命周期

      • InitializingBean
      • DisposableBean

参考

请别再问Spring Bean的生命周期了!
Spring Bean 生命周期