【深入学习Spring】5——Bean的初始化/销毁的几种方式总结

一、Bean初始化的几种方式

1.使用@Bean指定初始化和销毁方法

@Configuration
public class LifeCycleConfig {

    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Color color() {
        return new Color();
    }

}

public class Color {

    public Color() {
        System.out.println("Color construct……");
    }

    public void init() {
        System.out.println("Color init……");
    }

    public void destroy() {
        System.out.println("Color destroy……");
    }

}

打印结果:
Color construct……
Color init……
Color destroy……

2.实现InitializingBean和Disposable接口

该方式的Bean会与Spring产生耦合,不推荐使用。

@Configuration
public class LifeCycleConfig {

    @Bean
    public Apple apple() {
        return new Apple();
    }

}

public class Apple implements InitializingBean, DisposableBean {

    public Apple() {
        System.out.println("Apple construct……");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Apple init……");
    }

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

打印结果:
Apple construct……
Apple init……
Apple destroy……

3.使用JSR250提供的@PostConstruct和@PreDestroy

@PostConstruct和@PreDestroy这两个注解是JSR-250提供的。

@Configuration
public class LifeCycleConfig {

    @Bean
    public Banana banana() {
        return new Banana();
    }

}

public class Banana {

    public Banana() {
        System.out.println("Banana construct……");
    }

    @PostConstruct
    public void init() {
        System.out.println("Banana init……");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("Banana destory……");
    }

}

打印结果:
Banana construct……
Banana init……
Banana destory……

4.使用BeanPostProcessor

使用后置处理器,BeanPostProcessor接口中定义了两个方法:postProcessBeforeInitialization和postProcessAfterInitialization方法,分别在Bean的初始化方法执行的前后执行。

该方式本质上不算是声明Bean的初始化方式,而仅仅是对bean的初始化方法的功能增强,但其在Spring中使用非常广泛,例如@Autowired。

说明:后置处理器的方式是Bean的统一前置后置处理,而不是基于某一个bean。从下面程序执行结果也可以看出,不仅Car实例被后置处理器处理了,Spring中的Bean也被后置处理器处理了。

@Configuration
public class LifeCycleConfig {

    @Bean
    public Car car() {
        return new Car();
    }

    @Bean
    public MyBeanPostProcessor myBeanPostProcessor() {
        return new MyBeanPostProcessor();
    }

}

public class Car {

    public Car() {
        System.out.println("Car construct……");
    }

}

//后置处理器
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("后置处理器BeforeInitialization:  " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("后置处理器AfterInitialization:  " + beanName);
        return bean;
    }
}

打印结果:
后置处理器BeforeInitialization:  org.springframework.context.event.internalEventListenerProcessor
后置处理器AfterInitialization:  org.springframework.context.event.internalEventListenerProcessor
后置处理器BeforeInitialization:  org.springframework.context.event.internalEventListenerFactory
后置处理器AfterInitialization:  org.springframework.context.event.internalEventListenerFactory
Car construct……
后置处理器BeforeInitialization:  car
后置处理器AfterInitialization:  car

二、Bean初始化的几种方式优先级

上面介绍了几种Bean的初始化和销毁方式,那么问题来了,这几种方式的优先级是怎样的呢?我们可以写个程序测试一下,只需要把几种方式同时都用上即可。

public class Mix implements InitializingBean, DisposableBean, BeanPostProcessor {

    /**
     * 构造方法
     */
    public Mix() {
        System.out.println("construct");
    }

    /*********************(第一顺序调用)下面使用JSR250方式指定*******************/
    @PostConstruct
    private void jsr250Init() {
        System.out.println("JSR250-->@PostConstruct");
    }

    @PreDestroy
    private void jsr250PreDestroy() {
        System.out.println("JSR250-->@PreDestroy");
    }

    /*********************(第二顺序调用)下面使用实现接口的方式指定*******************/
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("实现InitializingBean接口-->afterPropertiesSet");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("实现DisposableBean接口-->destroy");
    }

    /*********************(第三顺序调用)下面使用@Bean方式的属性指定*******************/
    private void initMethod() {
        System.out.println("@Bean指定的方法-->initMethod");
    }

    private void destroyMethod() {
        System.out.println("@Bean指定的方法-->destroyMethod");
    }

}

配置类

@Configuration
public class MixConfig {

    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public Mix mix() {
        return new Mix();
    }

    @Bean
    public MyBeanPostProcessor myBeanPostProcessor() {
        return new MyBeanPostProcessor();
    }

}

下面就来调用一下,看看执行结果

public class MixMain {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MixConfig.class);
        context.destroy();
    }
}

执行结果如下:

后置处理器BeforeInitialization:  org.springframework.context.event.internalEventListenerProcessor
后置处理器AfterInitialization:  org.springframework.context.event.internalEventListenerProcessor
后置处理器BeforeInitialization:  org.springframework.context.event.internalEventListenerFactory
后置处理器AfterInitialization:  org.springframework.context.event.internalEventListenerFactory

construct……
后置处理器BeforeInitialization:  mix
JSR250-->@PostConstruct
实现InitializingBean接口-->afterPropertiesSet
@Bean指定的方法-->initMethod
后置处理器AfterInitialization:  mix

JSR250-->@PreDestroy
实现DisposableBean接口-->destroy
@Bean指定的方法-->destroyMethod

因此,几种初始化调用顺序如下图所示:

三、Bean销毁的几种方式优先级

Bean的销毁就不再写程序去验证了,在Spring源码系列4 - Bean的生命周期中已经分析过源码了。Bean销毁的执行顺序与Bean初始化的执行顺序是一致的。

posted @ 2020-02-27 22:47  静水楼台/Java部落阁  阅读(698)  评论(0编辑  收藏  举报