在上一篇文章《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的生命周期中的特定阶段执行自定义的逻辑,从而实现更精细化的控制和管理。
领取专属 10元无门槛券
私享最新 技术干货