Bean生命周期
有时候我们需要在Bean构造过程中的各个时机,执行一些增强逻辑,这时候Spring为我们提供了多种灵活的构造时的增强方式,这些增强方式组成了Bean生命周期的一部分

指定初始化和销毁方法
initMethod
在指定一个Bean时,我们可以绑定一个initMethod,Spring在完成这个Bean的实例化之后,会调用绑定的initMethod
@Data
public class Person {
private int age;
private String name;
public Person(int age, String name) {
System.out.println("执行构造器");
this.age = age;
this.name = name;
}
public void doInit() {
System.out.println("执行初始化方法");
}
}
设置@Bean的initMethod属性为初始化方法的方法名
@Configuration
public class MyConfiguration {
@Bean(initMethod = "doInit")
public Person person() {
return new Person(18, "wang");
}
}

可以看到Spring在执行完构造器之后调用了绑定的doInit方法
destroyMethod
destroyMethod的使用方法和initMethod是一样的,一个是初始化时调用,一个是销毁时调用
@Data
public class Person {
private int age;
private String name;
public Person(int age, String name) {
System.out.println("执行构造器");
this.age = age;
this.name = name;
}
public void doDestroy() {
System.out.println("执行销毁方法");
}
}
@Configuration
public class MyConfiguration {
@Bean(destroyMethod = "doDestroy")
public Person person() {
return new Person(18, "wang");
}
}

在测试方法结束时,Spring的IOC容器会关闭,当容器关闭时或当我们使用BeanDefinitionRegistryPostProcessor接口移除一个Bean时,将会调用绑定的销毁方法
实现初始化和销毁接口
InitializingBean
Spring提供了一个InitializingBean接口,我们可以在定义Bean时实现这个接口,并重写afterPropertiesSet方法
@Data
public class Person implements InitializingBean {
private int age;
private String name;
public Person(int age, String name) {
System.out.println("执行构造器");
this.age = age;
this.name = name;
}
@Override
public void afterPropertiesSet() {
System.out.println("执行afterPropertiesSet");
}
}
测试结果如下

效果跟initMethod也是一样的,在Bean完成实例化之后执行
DisposableBean
有用于初始化的接口,就有用于销毁的接口,可以看到这些Spring提供的方式都是成对出现的
在定义Bean时实现DisposableBean接口,并重写destroy方法,可以在Bean销毁的时候调用
@Data
public class Person implements DisposableBean {
private int age;
private String name;
public Person(int age, String name) {
System.out.println("执行构造器");
this.age = age;
this.name = name;
}
@Override
public void destroy() {
System.out.println("执行destroy");
}
}

使用Java原生注解
除了Spring之外,Java也提供了两个注解@PostConstruct和,Spring底层对这两个注解进行了处理
@PostConstruct
我们只需要在Bean中的方法上标注@PostConstruct注解,这个方法将会在Bean构造完成之后执行
@Data
public class Person {
private int age;
private String name;
public Person(int age, String name) {
System.out.println("执行构造器");
this.age = age;
this.name = name;
}
@PostConstruct
public void doPostConstruct() {
System.out.println("执行PostConstruct");
}
}

@PreDestroy
@PreDestroy的使用方式跟@PostConstruct一样,只需要标注在需要在Bean销毁时执行的方法上即可
@Data
public class Person {
private int age;
private String name;
public Person(int age, String name) {
System.out.println("执行构造器");
this.age = age;
this.name = name;
}
@PreDestroy
public void doPerDestroy(){
System.out.println("执行PerDestroy");
}
}

使用后置处理器
除了以上方式外,Spring还提供了一个后置处理器来增强Bean的初始化,我们可以通过实现BeanPostProcessor接口来编写我们自定义的后置处理器
@Component
public class MyBeanProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization->" + bean);
System.out.println("postProcessBeforeInitialization->" + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization->" + bean);
System.out.println("postProcessAfterInitialization->" + beanName);
return bean;
}
}
创建一个自定义的组件类,实现BeanPostProcessor接口,并重写postProcessBeforeInitialization和postProcessAfterInitialization方法,这两个方法分别会在Bean的初始化之前和之后执行
注意组件类需要添加@Component注解,这样组件类才会添加到IOC容器中被Spring获取到来执行
postProcessBeforeInitialization和postProcessAfterInitialization方法中,参数列表的bean即为处理的bean对象,beanName为bean的名称。方法返回一个Object对象,我们可以拿到传入的bean对象,返回原来的bean对象,或者对bean进行一些处理,返回处理之后的bean
后置处理器和前面的方式的区别是,他会对每一个Bean都生效,Spring在初始化每一个Bean时,会在IOC容器中寻找每一个后置处理器,包括Spring自带的和我们自定义的,遍历这些处理器执行其中的逻辑
我们在测试中将initMethod也添加上,方便测试后置处理器中两个方法的执行时机
测试结果如下

可以看到后置处理器确实对每一个Bean都进行了处理,除了我们自己添加的Person对象,还有好多Spring自带的Bean。
Spring会在我们执行初始化方法之前执行postProcessBeforeInitialization方法,之后执行postProcessAfterInitialization方法。
另外如果需要增强Bean的构造过程,可以使用InstantiationAwareBeanPostProcessor这个接口,使用方法大同小异
执行顺序
现在我们把每一种方式都用上,测试他们的执行顺序
Bean的定义
@Data
public class Person implements InitializingBean, DisposableBean {
private int age;
private String name;
public Person(int age, String name) {
System.out.println("执行构造器");
this.age = age;
this.name = name;
}
public void doInit() {
System.out.println("执行初始化方法");
}
public void doDestroy() {
System.out.println("执行销毁方法");
}
@Override
public void afterPropertiesSet() {
System.out.println("执行afterPropertiesSet");
}
@Override
public void destroy() {
System.out.println("执行destroy");
}
@PostConstruct
public void doPostConstruct() {
System.out.println("执行PostConstruct");
}
@PreDestroy
public void doPerDestroy() {
System.out.println("执行PerDestroy");
}
}
后置处理器
@Component
public class MyBeanProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Person) {
System.out.println("postProcessBeforeInitialization->" + bean);
System.out.println("postProcessBeforeInitialization->" + beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Person) {
System.out.println("postProcessAfterInitialization->" + beanName);
System.out.println("postProcessAfterInitialization->" + bean);
}
return bean;
}
}
添加Bean
@Configuration
public class MyConfiguration {
@Bean(initMethod = "doInit", destroyMethod = "doDestroy")
public Person person() {
return new Person(18, "wang");
}
}
测试结果如下

可以得出执行顺序
- 执行构造方法
- 执行后置处理器的
postProcessBeforeInitialization方法 - 执行
@PostConstruct标注的方法 - 执行
InitializingBean的afterPropertiesSet方法 - 执行初始化方法
- 执行后置处理器的
postProcessAfterInitialization方法 - 完成初始化
- 执行
@PreDestroy标注的方法 - 执行
DisposableBean的destroy方法 - 执行销毁方法
本文详细探讨了如何在Spring中利用initMethod、destroyMethod、InitializingBean和DisposableBean接口,以及Java原生注解@PostConstruct和@PreDestroy来定制Bean的构造和生命周期管理。此外,还包括了后置处理器BeanPostProcessor的应用,以及各种方法的执行顺序解析。

被折叠的 条评论
为什么被折叠?



