首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

在Spring Bean生命周期的不同阶段如何插入自定义的处理逻辑?Spring框架提供了两种类型的接口

在上一篇文章《Spring框架Bean生命周期的5个阶段及举例说明》中提到:Spring IoC容器管理Bean的生命周期,允许开发者在不同的生命周期阶段插入自定义的处理逻辑。

现在,我们要在Bean的不同的生命周期阶段插入自定义的处理逻辑,怎么插入呢?

Spring框架提供了两种类型的接口供我们实现,一类是直接应用在具体某个bean上的,一类是针对项目中全部bean的接口。

一、需要具体bean实现的接口

1、InitializingBean 接口

InitializingBean根据字面意思可以理解为正在初始化的Bean,提供可重写的初始化方法。

它定义了一个方法:

void afterPropertiesSet()

该方法在容器完成属性注入后会自动调用。

属性注入是Bean生命周期的第二个阶段。

2、DisposableBean 接口

DisposableBean接口的作用是提供可重写的销毁方法。

它定义了一个方法:

void destroy()

该方法在容器销毁 Bean 时会自动调用。执行自定义的销毁逻辑在Bean生命周期的第5个阶段。

除了实现接口,还可以使用 @PostConstruct 和 @PreDestroy 注解来定义初始化和销毁方法。

二、针对全部bean的实现接口

1、BeanFactoryPostProcessor 接口

BeanFactoryPostProcessor接口的作用是允许客户在实例化之前修改bean的描述对象BeanDefinition。

它提供了一个方法:

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

该方法在Bean生命周期之前调用。

2、InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor类名中有个单词Instantiation是实例化的意思,作用是提供在实例化时的执行方法。

它提供了三个方法:

Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)

该方法在实例化 Bean 之前调用。

boolean postProcessAfterInstantiation(Object bean, String beanName)

该方法在实例化 Bean 之后调用。

PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)

该方法在属性设置、依赖注入之前调用。

实例化是Bean生命周期的第1个阶段,属性设置是Bean生命周期的第2个阶段。

3、SmartInstantiationAwareBeanPostProcessor接口

SmartInstantiationAwareBeanPostProcessor是InstantiationAwareBeanPostProcessor的扩展,一个bean有一个默认无参构造函数,还有其他带参数的构造函数,这个类的作用就是给bean增加新的带参数的构造函数。

它提供了三个方法:

Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)

该方法提供了自定义选择构造器的能力。

Class<?> predictBeanType(Class<?> beanClass, String beanName)

该方法用于获取Bean的类型。

Object getEarlyBeanReference(Object bean, String beanName)

该方法有助于解决循环依赖问题。

这三个方法,都在Bean生命周期的第1个阶段实例化之前调用。

4、BeanPostProcessor 接口

BeanPostProcessor接口给开发者提供了一个钩子,用来修改bean实例。

它提供了两个方法:

Object postProcessBeforeInitialization(Object bean, String beanName)

该方法在 Bean 初始化前调用。

Object postProcessAfterInitialization(Object bean, String beanName)

该方法在 Bean 初始化后调用。

Bean生命周期的第3个阶段是初始化方法的执行。

5、DestructionAwareBeanPostProcessor接口

DestructionAwareBeanPostProcessor 是 BeanPostProcessor 的子接口,在bean销毁之前调用。

它提供2个方法:

postProcessBeforeDestruction(Object bean, String beanName)

该方法在bean销毁之前调用。

boolean requiresDestruction(Object bean)

该方法在bean销毁之前调用,主要用于是否必须请求销毁方法,默认true。

Bean生命周期的第5个阶段是销毁方法。

三、综合应用

1、针对单个bean的生命周期接口

@Componentpublic class MyBean implements InitializingBean, DisposableBean{ public MyBean() { System.out.println("1、实例化 MyBean2"); } @Value("${spring.tel}") public void setTel(String tel){ System.out.println("2、属性设置 tel=" + tel); } @PostConstruct public void init(){ System.out.println("3、MyBean2 @PostConstruct 初始化方法"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("3、MyBean2 InitializingBean接口的初始化方法"); } public void fun(){ System.out.println("4、调用 MyBean2 的 fun 方法"); } @PreDestroy public void close() { System.out.println("5、MyBean2 @PreDestroy 销毁方法"); }

@Override public void destroy() throws Exception { System.out.println("5、MyBean2 DisposableBean接口的 销毁方法"); }}

构建一个bean,实现InitializingBean、DisposableBean接口,重写接口中的方法,以便调用初始化和销毁方法。

同时也增加了@PostConstruct、@PreDestroy注解方法,以便观察两种初始化、销毁方法的执行顺序。

2、针对全部bean的生命周期接口

/** * 拦截所有的对象,对符合条件的对象进行修改 * @author * @date 2024年4月24日 * @Description * */@Componentpublic class MyProcessor implements BeanFactoryPostProcessor,InstantiationAwareBeanPostProcessor, SmartInstantiationAwareBeanPostProcessor, BeanPostProcessor, DestructionAwareBeanPostProcessor{ // 提前预设属性参数,在bean定义BeanDefinition的时候(BeanFactoryPostProcessor),实例化方法之前 @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println(); System.out.println("------提前预设属性参数:BeanFactoryPostProcessor 接口"); System.out.println(); } // 实例化之前(InstantiationAwareBeanPostProcessor) @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { System.out.println(); System.out.println("------实例化之前(InstantiationAwareBeanPostProcessor接口):" + beanName); return null; } // 实例化之前,自定义构造器类型(SmartInstantiationAwareBeanPostProcessor) @Override public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException { System.out.println("------实例化之前,自定义构造器类型(SmartInstantiationAwareBeanPostProcessor):" + beanName); return null; } // 实例化之后(InstantiationAwareBeanPostProcessor) @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { System.out.println("------实例化之后:(InstantiationAwareBeanPostProcessor)" + beanName); System.out.println(); return true; } // 属性设置之前(InstantiationAwareBeanPostProcessor) @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { System.out.println("------属性设置之前:(InstantiationAwareBeanPostProcessor)"); return null; } // 初始化方法之前(BeanPostProcessor) @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println(); System.out.println("------初始化方法前:(BeanPostProcessor)" + beanName); return bean; } // 初始化方法之后(BeanPostProcessor) @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("------初始化方法后:(BeanPostProcessor)" + beanName); System.out.println(); return bean; }

// 销毁方法之前(DestructionAwareBeanPostProcessor) @Override public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException { System.out.println(); System.out.println("------执行销毁方法之前:(DestructionAwareBeanPostProcessor)" + beanName); }}

单独构建一个针对全部bean的组件,实现BeanFactoryPostProcessor,InstantiationAwareBeanPostProcessor,

SmartInstantiationAwareBeanPostProcessor, BeanPostProcessor, DestructionAwareBeanPostProcessor 5个接口,并覆盖每个接口中的方法,以便观察它们在单个bean的生命周期中的执行顺序。

3、测试代码

import java.lang.reflect.Constructor;

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

import org.springframework.beans.BeansException;import org.springframework.beans.PropertyValues;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;import org.springframework.beans.factory.annotation.Value;import org.springframework.beans.factory.config.BeanFactoryPostProcessor;import org.springframework.beans.factory.config.BeanPostProcessor;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.stereotype.Component;/** * Bean生命周期接口演示代码 * @author * @Description */@SpringBootApplicationpublic class SpringApp4 { public static void main(String[] args) { // ConfigurableApplicationContext context = SpringApplication.run(SpringApp4.class, args); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyBean.class, MyProcessor.class); MyBean myBean = context.getBean(MyBean.class); myBean.fun(); // 关闭上下文,调用销毁方法 context.close(); }}

使用 AnnotationConfigApplicationContext 上下文,有针对性地加载了MyBean.class, MyProcessor.class两个对象,以方便查看上述接口在生命周期中的执行顺序。

运行结果:

通过上面的运行结果我们看到,BeanFactoryPostProcessor接口的方法在Bean的生命周期之前执行,也就是在实例化之前调用。其他6个接口和两个注解在bean的生命周期中执行。

上述代码只是做了一个简单的演示,要加什么业务代码,还要看业务需求。

最后总结

Spring框架在一个Bean的不同生命周期阶段都有提供钩子,以供在不同的阶段增加自定义方法,实际上不止这7个接口,还有更多可能选择。我们先了解一下,以便在使用的时候逐步深入。

通过实现以上接口的实现,或者使用注解,我们可以在Bean的生命周期中的特定阶段执行自定义的逻辑,从而实现更精细化的控制和管理。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/Oyj_y7Ojayc5e0jOQtAX6rTQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券