详解 Spring Bean 的生命周期以及实际应用

1 概述

本文详解 Spring Bean 的生命周期,具体是通过 Spring 的 IOC 容器在启动过程中,以及 Bean 的创建,配置,以及销毁的过程中的一些回调接口来验证的。具体包含以下内容:

  1. Spring Bean 的生命周期流程图
  2. 实现相关接口的 Bean 并注册到 Spring IOC 容器,容器在启动后会自动调用自定义 Bean 中的方法
  3. 自定义 Bean 实现了这些声明周期的回调接口能做些什么,这里结合 BeanFactoryPostProcessor 实现了一个基于订单处理的策略设计模式

2 Spring Bean 的生命周期流程图

Spring Bean 的完整生命周期从创建 Spring 容器开始,直到最终 Spring 容器销毁 Bean,这其中包含了一系列回调方法。具体如下

Spring Bean 的生命周期流程图
Spring Bean 的生命周期流程图

3 各种接口方法分类

Bean 的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

  1. Bean 自身的方法: 这个包括了 Bean 本身调用的方法和通过 @PostConstruct@PreDestroy 指定的方法
  2. Bean 级生命周期接口方法: 这个包括了 BeanNameAware、BeanFactoryAware、InitializingBean 和 DiposableBean 这些接口的方法
  3. 容器级生命周期接口方法: 这个包括了 InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
  4. 工厂后处理器接口方法: 这个包括了 AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer 等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

4 验证

4.1 Bean 自身的方法

  • TestBeanMethod 自身实现了 BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean 这四个接口,并通过 @PostConstruct@PreDestroy 指定了初始化后以及销毁前的方法,具体如下
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
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class TestBeanMethod implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {

private static final Logger logger = LoggerFactory.getLogger(TestBeanMethod.class);

private BeanFactory beanFactory;
private String beanName;
private String phone;

public String getBeanName() {
return beanName;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
logger.info("【注入属性】注入属性 phone");
this.phone = phone;
}

public TestBeanMethod() {
logger.info("【构造器】调用构造方法初始化 bean");
}

// 获取 BeanFactory 对象
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
logger.info("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");
}

@PostConstruct
public void init() {
logger.info("【@PostConstruct】自定义 init 方法");
}

@PreDestroy
public void des() {
logger.info("【@PreDestroy】自定义 destroy 方法");
}

@Override
public void setBeanName(String s) {
this.beanName = s;
logger.info("【注入属性】注入属性name");
}

@Override
public void destroy() throws Exception {
logger.info("【DisposableBean接口】调用DisposableBean.destroy()");
}

@Override
public void afterPropertiesSet() throws Exception {
logger.info("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
}

}

4.2 实现 BeanPostProcessor 接口

  • TestBeanPostProcessor

BeanPostProcessor 接口包括 2个方法 postProcessAfterInitialization 和 postProcessBeforeInitialization,这两个方法的第一个参数都是要处理的 Bean 对象,第二个参数都是 Bean 的 name。返回值也都是要处理的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
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
* 在 Bean 的初始化前后执行
*/
@Component
public class TestBeanPostProcessor implements BeanPostProcessor {

private static final Logger logger = LoggerFactory.getLogger(TestBeanPostProcessor.class);

public TestBeanPostProcessor() {
super();
logger.info("这是 BeanPostProcessor 实现类构造器!!");
}

@Override
public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException {
logger.info("BeanPostProcessor 接口方法 postProcessAfterInitialization 对属性进行更改!");
return arg0;
}

@Override
public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException {
logger.info("BeanPostProcessor 接口方法 postProcessBeforeInitialization 对属性进行更改!");
return arg0;
}
}

4.3 实现 InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor 接口本质是 BeanPostProcessor 的子接口,一般继承 Spring 为其提供的适配器类 InstantiationAwareBeanPostProcessor Adapter 来使用它,如下

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
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.stereotype.Component;

@Component
public class TestInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {

private static final Logger logger = LoggerFactory.getLogger(TestInstantiationAwareBeanPostProcessor.class);

public TestInstantiationAwareBeanPostProcessor() {
super();
logger.info("这是 InstantiationAwareBeanPostProcessorAdapter 实现类构造器!!");
}

// 接口方法、实例化Bean之前调用
@Override
public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
logger.info(String.format("InstantiationAwareBeanPostProcessor 调用 postProcessBeforeInstantiation方法,beanName=%s", beanName));
return null;
}

// 接口方法、实例化Bean之后调用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
logger.info(String.format("InstantiationAwareBeanPostProcessor 调用 postProcessAfterInitialization方法,beanName=%s", beanName));
return bean;
}

}

4.4 实现 BeanFactoryPostProcessor 接口

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
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

private static final Logger logger = LoggerFactory.getLogger(TestBeanFactoryPostProcessor.class);

public TestBeanFactoryPostProcessor() {
super();
logger.info("这是 BeanFactoryPostProcessor 实现类构造器!!");
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException {
logger.info("BeanFactoryPostProcessor 调用 postProcessBeanFactory 方法");
BeanDefinition bd = arg0.getBeanDefinition("testSpringBeanLifeCircle");
bd.getPropertyValues().addPropertyValue("phone", "110");
}

}
  • 通过 AnnotationConfigApplicationContext 启动和销毁 Spring 容器,具体如下
1
2
3
4
5
6
7
8
9
10
11
12
13
import com.toulezu.test.component.TestBeanMethod;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ApplicationContextRun {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.toulezu.test");

TestBeanMethod testBeanMethod = applicationContext.getBean(TestBeanMethod.class);

((AnnotationConfigApplicationContext) applicationContext).registerShutdownHook();
}
}
  • 输出如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
15:59:09.654 [main] INFO  c.t.t.c.TestBeanFactoryPostProcessor - 这是 BeanFactoryPostProcessor 实现类构造器!!
15:59:09.654 [main] INFO c.t.t.c.TestBeanFactoryPostProcessor - BeanFactoryPostProcessor 调用 postProcessBeanFactory 方法
15:59:09.745 [main] INFO c.t.t.c.TestInstantiationAwareBeanPostProcessor - 这是 InstantiationAwareBeanPostProcessorAdapter 实现类构造器!!
15:59:09.883 [main] INFO c.t.t.c.TestBeanPostProcessor - 这是 BeanPostProcessor 实现类构造器!!
15:59:10.494 [main] INFO c.t.t.c.TestBeanPostProcessor - BeanPostProcessor 接口方法 postProcessAfterInitialization 对属性进行更改!
15:59:10.494 [main] INFO c.t.t.c.TestInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessor 调用 postProcessBeforeInstantiation方法,beanName=testSpringBeanLifeCircle
15:59:10.494 [main] INFO c.t.test.component.TestBeanMethod - 【构造器】调用构造方法初始化 bean
15:59:10.498 [main] INFO c.t.test.component.TestBeanMethod - 【注入属性】注入属性 phone
15:59:10.499 [main] INFO c.t.test.component.TestBeanMethod - 【注入属性】注入属性name
15:59:10.499 [main] INFO c.t.test.component.TestBeanMethod - 【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()
15:59:10.499 [main] INFO c.t.t.c.TestBeanPostProcessor - BeanPostProcessor 接口方法 postProcessBeforeInitialization 对属性进行更改!
15:59:10.499 [main] INFO c.t.test.component.TestBeanMethod - 【@PostConstruct】自定义 init 方法
15:59:10.499 [main] INFO c.t.test.component.TestBeanMethod - 【InitializingBean接口】调用InitializingBean.afterPropertiesSet()
15:59:10.500 [main] INFO c.t.t.c.TestInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessor 调用 postProcessAfterInitialization方法,beanName=testSpringBeanLifeCircle
15:59:11.434 [main] INFO c.t.t.c.TestBeanPostProcessor - BeanPostProcessor 接口方法 postProcessAfterInitialization 对属性进行更改!
15:59:11.462 [SpringContextShutdownHook] INFO c.t.test.component.TestBeanMethod - 【@PreDestroy】自定义 destroy 方法
15:59:11.462 [SpringContextShutdownHook] INFO c.t.test.component.TestBeanMethod - 【DisposableBean接口】调用DisposableBean.destroy()

5 使用场景

这里结合策略设计模式 和 BeanFactoryPostProcessor 的实现类,来处理一个根据 不同的订单类型 使用 不同的处理器功能。

好处如下:

  1. 订单类型的处理 通过 订单类型注解(OrderHandlerType)和实现 AbstractOrderHandler 接口就可以扩展,实现了“高内聚和低耦合”。
  2. 取消了 if...else if...,代码容易阅读和理解。

5.1 订单处理注解

订单处理注解,用于标注订单的处理类型,具体如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import com.ckjava.test.entity.OrderTypeEnum;

import java.lang.annotation.*;

/**
* 订单处理注解,用于标注订单的处理类型
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface OrderHandlerType {
// 订单处理类型
OrderTypeEnum value() default OrderTypeEnum.offline;
}

5.2 实现 BeanFactoryPostProcessor 接口

  1. 实现 BeanFactoryPostProcessor 接口,用于在 Spring 容器启动成功后从容器中获取 AbstractOrderHandler 接口的实现类
  2. 并将实现类存入到 订单处理容器中

具体如下

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
import com.ckjava.test.annotation.OrderHandlerType;
import com.ckjava.test.entity.OrderTypeEnum;
import com.ckjava.test.handler.AbstractOrderHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
* 1. 实现 BeanFactoryPostProcessor 接口,用于在 Spring 容器启动成功后从容器中获取 AbstractOrderHandler 接口的实现类 <br>
* 2. 并将实现类存入到 订单处理容器中
*
*/
@Component
public class OrderBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

public OrderBeanFactoryPostProcessor() {
super();
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 1. 获取 AbstractOrderHandler 接口的实现类
Map<String, AbstractOrderHandler> orderHandlerMap = beanFactory.getBeansOfType(AbstractOrderHandler.class);
// 2. 订单类别 对应的 具体实现类
Map<OrderTypeEnum, Class<?>> map = new HashMap<>();

orderHandlerMap.forEach((k,v) -> {
OrderHandlerType orderHandlerType = v.getClass().getDeclaredAnnotation(OrderHandlerType.class);
OrderTypeEnum orderTypeEnum = orderHandlerType.value();
map.put(orderTypeEnum, v.getClass());
});
// 将 订单类别 对应的 具体实现类 的 map 存储到 applicationContext 中
beanFactory.registerSingleton(OrderHandlerType.class.getName(), map);
}

}

5.3 订单的实体和订单类型枚举

  • OrderEntity
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
import java.math.BigDecimal;
import java.util.Date;

/**
* 订单实体
*/
public class OrderEntity {

private Long id;
private Long userId;
private OrderTypeEnum orderType;
private Date orderDate;
private BigDecimal orderAmount;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public Long getUserId() {
return userId;
}

public void setUserId(Long userId) {
this.userId = userId;
}

public Date getOrderDate() {
return orderDate;
}

public void setOrderDate(Date orderDate) {
this.orderDate = orderDate;
}

public BigDecimal getOrderAmount() {
return orderAmount;
}


public void setOrderAmount(BigDecimal orderAmount) {
this.orderAmount = orderAmount;
}

public OrderTypeEnum getOrderType() {
return orderType;
}

public void setOrderType(OrderTypeEnum orderType) {
this.orderType = orderType;
}

public OrderEntity(Long id, Long userId, OrderTypeEnum orderType, Date orderDate, BigDecimal orderAmount) {
this.id = id;
this.userId = userId;
this.orderType = orderType;
this.orderDate = orderDate;
this.orderAmount = orderAmount;
}

public OrderEntity() {
}
}
  • OrderTypeEnum
1
2
3
4
5
6
/**
* 订单类型枚举
*/
public enum OrderTypeEnum {
online, offline;
}

5.4 订单处理接口

  • 订单处理接口
1
2
3
4
5
6
7
8
9
import com.ckjava.test.entity.OrderEntity;

/**
* 订单处理接口
*/
public interface AbstractOrderHandler {

void handle(OrderEntity orderEntity);
}

5.5 订单处理容器

订单处理容器,根据订单类型返回对应的 订单处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import com.ckjava.test.annotation.OrderHandlerType;
import com.ckjava.test.entity.OrderTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
* 订单处理容器,根据订单类型返回对应的 订单处理器
*/
@Component
public class OrderHandlerContext {

@Autowired
private ApplicationContext applicationContext;

public AbstractOrderHandler getOrderHandler(OrderTypeEnum orderTypeEnum) {
Map<OrderTypeEnum, Class<?>> map = applicationContext.getBean(OrderHandlerType.class.getName(), Map.class);

Class<?> clazz = map.get(orderTypeEnum);
return (AbstractOrderHandler) applicationContext.getBean(clazz);
}
}

5.6 具体的订单处理器

  • 处理线下订单, 带有 @OrderHandlerType(OrderTypeEnum.offline) 注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import com.ckjava.test.annotation.OrderHandlerType;
import com.ckjava.test.entity.OrderEntity;
import com.ckjava.test.entity.OrderTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
* 处理线下订单
*/
@Component
@OrderHandlerType(OrderTypeEnum.offline)
public class ProcessOfflineOrderHandler implements AbstractOrderHandler {

private static final Logger logger = LoggerFactory.getLogger(ProcessOfflineOrderHandler.class);

@Override
public void handle(OrderEntity orderEntity) {
logger.info("order handler,type={}", orderEntity.getOrderType());
}
}
  • 处理线上订单,带有 @OrderHandlerType(OrderTypeEnum.online) 注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import com.ckjava.test.annotation.OrderHandlerType;
import com.ckjava.test.entity.OrderEntity;
import com.ckjava.test.entity.OrderTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
* 处理线上订单
*/
@Component
@OrderHandlerType(OrderTypeEnum.online)
public class ProcessOnlineOrderHandler implements AbstractOrderHandler {

private static final Logger logger = LoggerFactory.getLogger(ProcessOnlineOrderHandler.class);

@Override
public void handle(OrderEntity orderEntity) {
logger.info("handle order,type {}", orderEntity.getOrderType());
}
}

5.7 测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.ckjava.test.entity.OrderEntity;
import com.ckjava.test.entity.OrderTypeEnum;
import com.ckjava.test.handler.AbstractOrderHandler;
import com.ckjava.test.handler.OrderHandlerContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ApplicationContextOrderRun {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.ckjava.test");

// 1. 获取订单处理上下文
OrderHandlerContext orderHandlerContext = applicationContext.getBean(OrderHandlerContext.class);
// 2. 传入的订单实体
OrderEntity orderEntity = new OrderEntity();
orderEntity.setOrderType(OrderTypeEnum.offline);
// 3. 根据订单类型获取对应的订单处理器
AbstractOrderHandler abstractOrderHandler = orderHandlerContext.getOrderHandler(orderEntity.getOrderType());
// 4. 最后处理订单
abstractOrderHandler.handle(orderEntity);
}
}
  • 输出如下
1
21:51:31.944 [main] INFO  c.c.t.h.ProcessOfflineOrderHandler - order handler,type=offline
Buy me a cup of coffee