【深入学习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初始化的执行顺序是一致的。
不积跬步,无以至千里。不积小流,无以成江海!