Spring中Bean生命周期管理的几种方法

  spring是java编程最常用的IoC框架,我们在平常的使用中会将用到的bean全部注入到spring的容器中,让spring帮助我们管理,在有些编码的场景中,我们需要人为的控制bean的生命周期,本文总结了几种控制spring中bean生命周期的方法,供大家参考。

1、在@Bean注解中指定initMethod 和 destroyMethod方法

  如果需要控制一个bean的初始化和销毁,可以在对象中创建对应的方法,并用@Bean注入到spring中,这时候只需要指定@Bean的initMethod 和 destroyMethod到具体的方法即可,示例代码如下:

  • 首先创建一个对象Car,并编写示例方法
public class Car {

    public Car(){
        System.out.println("构造方法");
    }

    public void addOil(){
        System.out.println("加油");
    }

    public void run(){
        System.out.println("启动");
    }

    public void close(){
        System.out.println("关闭熄火");
    }
}
  • 编写一个配置类LifycycleConfig,用@Bean注解将Car注入到Spring容器中,并用initMethod 和 destroyMethod指定初始化和销毁方法
@Configuration
public class LifycycleConfig {

    @Bean(initMethod = "addOil", destroyMethod = "close")
    public Car car() {
        return new Car();
    }
}
  • 编写一个测试类LifecycleTest,并编写对应的测试方法
public class LifecycleTest {

    @Test
    public void testBeanAnnotationConfig() {
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(LifycycleConfig.class);
        System.out.println("-----------IoC容器创建完成------------------");
        Car car = app.getBean(Car.class);
        car.run();
        app.close();
    }
}

测试结果如下:

构造方法
加油
-----------IoC容器创建完成------------------
启动
五月 07, 2023 5:09:52 下午 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@161cd475: startup date [Sun May 07 17:09:51 CST 2023]; root of context hierarchy
关闭熄火

  从上面的结果中可以看出,spring在创建完Car对象后,自动调用了initMethod 指定的addOil方法,在spring容器关闭的时候,自动调用了destroyMethod 指定的close方法。这里有一点需要注意,spring关闭容器需要显示的调用close()方法,我们平常的指点点击关闭按钮或者用kill 的方式,是没法调用到close()方法的,自然也就调用不到我们的destroy方法,所以一些重要的销毁逻辑不能写在依赖spring的destroy方法的逻辑中

2、 实现InitializingBean和DisposableBean接口

  可以让bean实现InitializingBean和DisposableBean接口,并实现对应的初始化或者销毁方法,这样将这个bean注入到spring容器中后,spring会按照指定的方法来实现生命周期的管理。示例代码如下:

  • 编写实现了InitializingBean和DisposableBean接口的对象Train
public class Train implements InitializingBean, DisposableBean {

    public void run(){
        System.out.println("启动");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("销毁");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化");
    }
}
  • 在LifycycleConfig中将Train注入spring容器中
    @Bean
    public Train train() {
        return new Train();
    }
  • 在LifecycleTest中编写测试方法
    @Test
    public void testInitializingBeanAndDisposableBean() {
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(LifycycleConfig.class);
        System.out.println("-----------IoC容器创建完成------------------");
        Train train = app.getBean(Train.class);
        train.run();
        app.close();
    }

测试结果如下:

初始化
-----------IoC容器创建完成------------------
启动
五月 07, 2023 5:18:27 下午 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@161cd475: startup date [Sun May 07 17:18:26 CST 2023]; root of context hierarchy
销毁

3、 使用@PostConstruct和@PreDestroy注解

  可以在Bean对应的方法上加上@PostConstruct和@PreDestroy注解,这样在构造方法调用完成,spring会调用加了@PostConstruct注解的方法,在spring容器要销毁的时候,会调用加了@PreDestroy注解的方法。示例代码如下:

  • 创建一个用@PostConstruct和@PreDestroy注解的bean
public class AirPlane {


    public void fly(){
        System.out.println("起飞");
    }

    @PostConstruct
    public void init(){
        System.out.println("启动前检查");
    }

    @PreDestroy
    public void stop(){
        System.out.println("降落停机");
    }
}

  • 在在LifycycleConfig中将AirPlane 注入spring容器中
    @Bean
    public AirPlane airPlane() {
        return new AirPlane();
    }
  • 在LifecycleTest中编写测试方法
    @Test
    public void testPostConstructAndPreDestroy() {
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(LifycycleConfig.class);
        System.out.println("-----------IoC容器创建完成------------------");
        AirPlane airPlane = app.getBean(AirPlane.class);
        airPlane.fly();
        app.close();
    }

测试结果如下:

启动前检查
-----------IoC容器创建完成------------------
起飞
五月 07, 2023 5:24:25 下午 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@161cd475: startup date [Sun May 07 17:24:25 CST 2023]; root of context hierarchy
降落停机

4、 使用BeanPostProcessor对创建的对象进行干预

  org.springframework.beans.factory.config.BeanPostProcessor接口是spring中一个非常重要的接口,看过源码的同学应该很清楚这个接口,因为这是spring中AOP等功能实现的基础,代理类就是在这个接口的方法中加入进去的,这个接口主要有两个方法,这两个方法是在初始化bean前后来调用的:接口会传进来bean的名称和创建的对象,然后经过处理后再返回一个新的对象,这样就可以在这里轻松加入代理对象。
  BeanPostProcessor接口具体来说无法实现像前面中自动销毁的逻辑,但是可以实现在初始化前后增加功能的逻辑,当然也就可以调用具体的方法。我们这里仅示例一下这个接口的调用过程:

  • 编写一个实现了BeanPostProcessor接口的类MyBeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization beanName="+ beanName);
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization beanName="+ beanName);
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}
  • 在LifycycleConfig中将MyBeanPostProcessor 注入spring容器中,同时注入一个测试的Bird对象
    @Bean
    public Bird bird() {
        return new Bird();
    }
    @Bean
    public BeanPostProcessor myBeanPostProcessor(){
        return new MyBeanPostProcessor();
    }
  • 在LifecycleTest中编写测试方法
    @Test
    public void testBeanPostProcessor() {
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(LifycycleConfig.class);
        System.out.println("-----------IoC容器创建完成------------------");
        Bird bird = app.getBean(Bird.class);
        app.close();
    }

测试结果:

postProcessBeforeInitialization beanName=org.springframework.context.event.internalEventListenerProcessor
postProcessAfterInitialization beanName=org.springframework.context.event.internalEventListenerProcessor
postProcessBeforeInitialization beanName=org.springframework.context.event.internalEventListenerFactory
postProcessAfterInitialization beanName=org.springframework.context.event.internalEventListenerFactory
 bird 构造方法
postProcessBeforeInitialization beanName=bird
postProcessAfterInitialization beanName=bird
-----------IoC容器创建完成------------------

  从上面测试结果中可以看出,spring会将所有创建的对象在初始化前后全部传给MyBeanPostProcessor 对象,让其对创建的对象进行修改,这种设计思路,使得我们给spring中的bean增加新的功能成为了一种可能,很好的支持了功能的扩展性,值得我们好好研究和借鉴。


后记
  个人总结,欢迎转载、评论、批评指正

你可能感兴趣的:(#,Spring应用,spring,java)