Bean生命周期

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

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("执行初始化方法");
    }

}

设置@BeaninitMethod属性为初始化方法的方法名

@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接口,并重写postProcessBeforeInitializationpostProcessAfterInitialization方法,这两个方法分别会在Bean的初始化之前和之后执行

注意组件类需要添加@Component注解,这样组件类才会添加到IOC容器中被Spring获取到来执行

postProcessBeforeInitializationpostProcessAfterInitialization方法中,参数列表的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");
    }

}

测试结果如下

在这里插入图片描述

可以得出执行顺序

  1. 执行构造方法
  2. 执行后置处理器的postProcessBeforeInitialization方法
  3. 执行@PostConstruct标注的方法
  4. 执行InitializingBeanafterPropertiesSet方法
  5. 执行初始化方法
  6. 执行后置处理器的postProcessAfterInitialization方法
  7. 完成初始化
  8. 执行@PreDestroy标注的方法
  9. 执行DisposableBeandestroy方法
  10. 执行销毁方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值