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

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

各种接口方法分类

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

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

2. 验证

2.1.实现 BeanFactoryPostProcessor 接口

Spring IoC容器允许BeanFactoryPostProcessor在容器实例化任何bean之前读取bean的定义(配置元数据),并可以修改它。同时可以定义BeanFactoryPostProcessor,通过设置order属性来确定各个BeanFactoryPostProcessor执行顺序。

@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("imageBase64Utils");
        bd.getPropertyValues().addPropertyValue("phone", "110");
    }
}
@Setter
@Getter
@Component
public class ImageBase64Utils {
    private String phone;
}

2.2.Bean 自身的方法

TestBeanMethod 自身实现了 BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean 这四个接口,并通过 @PostConstruct 和 @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()");
    }
}

2.3.实现 InstantiationAwareBeanPostProcessor

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

@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;
    }
}

2.4.实现 BeanPostProcessor 接口

BeanPostProcessor 接口包括 2个方法 postProcessAfterInitialization 和 postProcessBeforeInitialization,这两个方法的第一个参数都是要处理的 Bean 对象,第二个参数都是 Bean 的 name。返回值也都是要处理的Bean对象。

/**
 * 在 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;
    }
}

2.5.测试

public class ApplicationContextRun {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext("cn.cychee.imageservice.logic");
        TestBeanMethod testBeanMethod = applicationContext.getBean(TestBeanMethod.class);
        ((AnnotationConfigApplicationContext) applicationContext).registerShutdownHook();
    }
}

2.6.测试结果

c.c.i.l.TestBeanFactoryPostProcessor    [19] 这是 BeanFactoryPostProcessor 实现类构造器!!
c.c.i.l.TestBeanFactoryPostProcessor    [24] BeanFactoryPostProcessor 调用 postProcessBeanFactory 方法
c.c.i.logic.TestBeanPostProcessor       [19] 这是 BeanPostProcessor 实现类构造器!!
.TestInstantiationAwareBeanPostProcessor[16] 这是 InstantiationAwareBeanPostProcessorAdapter 实现类构造器!!
.TestInstantiationAwareBeanPostProcessor[22] InstantiationAwareBeanPostProcessor 调用 postProcessBeforeInstantiation方法,beanName=imageBase64Utils
c.c.i.logic.TestBeanPostProcessor       [30] BeanPostProcessor 接口方法 postProcessBeforeInitialization 对属性进行更改!
c.c.i.logic.TestBeanPostProcessor       [24] BeanPostProcessor 接口方法 postProcessAfterInitialization 对属性进行更改!
.TestInstantiationAwareBeanPostProcessor[29] InstantiationAwareBeanPostProcessor 调用 postProcessAfterInitialization方法,beanName=imageBase64Utils
.TestInstantiationAwareBeanPostProcessor[22] InstantiationAwareBeanPostProcessor 调用 postProcessBeforeInstantiation方法,beanName=testBeanMethod
c.c.imageservice.logic.TestBeanMethod   [35] 【构造器】调用构造方法初始化 bean
c.c.imageservice.logic.TestBeanMethod   [58] 【注入属性】注入属性name
c.c.imageservice.logic.TestBeanMethod   [42] 【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()
c.c.i.logic.TestBeanPostProcessor       [30] BeanPostProcessor 接口方法 postProcessBeforeInitialization 对属性进行更改!
c.c.imageservice.logic.TestBeanMethod   [47] 【@PostConstruct】自定义 init 方法
c.c.imageservice.logic.TestBeanMethod   [68] 【InitializingBean接口】调用InitializingBean.afterPropertiesSet()
c.c.i.logic.TestBeanPostProcessor       [24] BeanPostProcessor 接口方法 postProcessAfterInitialization 对属性进行更改!
.TestInstantiationAwareBeanPostProcessor[29] InstantiationAwareBeanPostProcessor 调用 postProcessAfterInitialization方法,beanName=testBeanMethod
c.c.imageservice.logic.TestBeanMethod   [52] 【@PreDestroy】自定义 destroy 方法
c.c.imageservice.logic.TestBeanMethod   [63] 【DisposableBean接口】调用DisposableBean.destroy()

3.使用场景

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

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

3.1.订单处理注解

订单处理注解,用于标注订单的处理类型

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface OrderHandlerType {
    // 订单处理类型
    OrderTypeEnum value() default OrderTypeEnum.offline;
}

3.2.实现 BeanFactoryPostProcessor 接口

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

/**
 * 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);
    }
}

3.3.订单的实体和订单类型枚举

  • OrderEntity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class OrderEntity {
    private Long id;
    private Long userId;
    private OrderTypeEnum orderType;
    private Date orderDate;
    private BigDecimal orderAmount;
}
  • OrderTypeEnum
/**
 * 订单类型枚举
 */
public enum OrderTypeEnum {
    online, offline;
}

3.4.订单处理接口

public interface AbstractOrderHandler {
    void handle(OrderEntity orderEntity);
}

3.5.订单处理容器

/**
 * 订单处理容器,根据订单类型返回对应的 订单处理器
 */
@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);
    }
}

3.6.具体的订单处理器

  • 处理线下订单, 带有@OrderHandlerType(OrderTypeEnum.offline)注解
@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)注解
@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());
    }
}

3.7.测试

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);
    }
}

原文

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