SpringBoot中的Bean的初始化與銷毀順序解析
我今天學(xué)習(xí)到SpringBoot里面自定義Bean的初始化與銷毀方法
我先總結(jié)一下我學(xué)到的四種方法:
方法一:
指定init-method 和 destory-method
方法二:
通過讓 Bean 實(shí)現(xiàn) InitializingBean 接口,定義初始化邏輯
DisposableBean 接口,定義銷毀邏輯
方法三:
用 @PostConstruct,在 Bean 創(chuàng)建完成并且賦值完成后,執(zhí)行該注解標(biāo)注的方法
@PreDestroy,在容器銷毀 Bean 之前,執(zhí)行該注解標(biāo)注的方法
方法四:
通過讓 Bean 實(shí)現(xiàn) BeanPostProcessor 接口,在Bean 初始化前后進(jìn)行一些處理工作
- postProcessBeforeInitialization: 在初始化之前工作
- postProcessAfterInitialization: 在初始化之后工作
然后我就在想它們的執(zhí)行順序是怎樣的:
嘗試一:
配置類:
//告訴Spring這是一個(gè)配置類 @Configuration public class MainConfigOfLifeCycle { //利用 init-method 和 destory-method @Bean(initMethod="initTest", destroyMethod="detoryTest") public Car car() { return new Car(); } //實(shí)現(xiàn) InitializingBean , DisposableBean 接口 @Bean public Cat cat() { return new Cat(); } //利用 @PostConstruct ,@PreDestroy @Bean public Dog dog() { return new Dog(); } //實(shí)現(xiàn) BeanPostProcessor 接口 @Bean public MyBeanPostProcessor myBeanPostProcessor() { return new MyBeanPostProcessor(); } }
4個(gè) bean:
public class Car{ public void initTest() { System.out.println(" .. init-method .. "); } public void detoryTest() { System.out.println(" .. destory-method .. "); } } public class Cat implements InitializingBean, DisposableBean { //該Bean在銷毀時(shí),調(diào)用 public void destroy() throws Exception { // TODO Auto-generated method stub System.out.println(" .. DisposableBean .."); } //該Bean創(chuàng)建完成并且賦值完成后,調(diào)用 public void afterPropertiesSet() throws Exception { // TODO Auto-generated method stub System.out.println(" .. InitializingBean .."); } } public class Dog { //對(duì)象創(chuàng)建并賦值之后調(diào)用 @PostConstruct public void init() { System.out.println(" .. @PostConstruct .. "); } //容器移除對(duì)象之前 @PreDestroy public void detory() { System.out.println(" .. @PreDestroy .. "); } } public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println(" .. postProcessBeforeInitialization .. "); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println(" .. postProcessBeforeInitialization .. "); return bean; } }
運(yùn)行:
public class IOCTest_LifeCycle { @Test public void test01() { // 1. 創(chuàng)建IOC容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class); System.out.println("容器創(chuàng)建完成"); // 關(guān)閉容器 applicationContext.close(); } }
執(zhí)行結(jié)果:
思考:發(fā)現(xiàn)容器在加載 Bean 時(shí)是順序的,因?yàn)槲以贛ainConfigOfLifeCycle這個(gè)配置類里 @Bean 是順序的,所有不能確定這次結(jié)果是否準(zhǔn)確。
嘗試二:我把上面四種方法都雜糅到一個(gè)類里
配置類:
@Configuration public class MainConfigOfLifeCycle { @Bean(initMethod="initTest", destroyMethod="detoryTest") public Car car() { return new Car(); } }
Bean:
public class Car implements InitializingBean, DisposableBean, BeanPostProcessor { public Car() { System.out.println("Car 創(chuàng)建"); } public void initTest() { System.out.println(" .. init-method .. "); } public void detoryTest() { System.out.println(" .. destory-method .. "); } @Override public void afterPropertiesSet() throws Exception { System.out.println(" .. InitializingBean .. "); } @Override public void destroy() throws Exception { System.out.println(" .. DisposableBean .. "); } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println(" .. postProcessBeforeInitialization .. "); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println(" .. postProcessAfterInitialization .. "); return bean; } @PostConstruct public void postConstructTest() { System.out.println(" .. @PostConstruct .. "); } @PreDestroy public void preDestroyTest() { System.out.println(" .. @PreDestroy .. "); } }
運(yùn)行:
public class IOCTest_LifeCycle { @Test public void test01() { // 1. 創(chuàng)建IOC容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class); System.out.println("容器創(chuàng)建完成"); // 關(guān)閉容器 applicationContext.close(); } }
執(zhí)行結(jié)果:
總結(jié):
創(chuàng)建:
- Bean 構(gòu)造函數(shù) ——> @PostConstruct ——> InitializingBean 接口 ——> bean 定義的 init-method——> postProcessBeforeInitialization ——> Bean 初始化完成 ——> postProcessAfterInitialization ——> 容器創(chuàng)建完成
銷毀:
- @PreDestroy ——> DisposableBean 接口 ——> bean 定義的 destoryMethod ——> Bean銷毀
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
mybatis對(duì)象List<String> List<Integer>屬性映射方式
這篇文章主要介紹了mybatis對(duì)象List<String> List<Integer>屬性映射方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12SpringBoot中的@Conditional?注解的使用
@Conditional是Spring4新提供的注解,它的作用是按照一定的條件進(jìn)行判斷,滿足條件的才給容器注冊(cè)Bean,本文主要介紹了SpringBoot中的@Conditional?注解的使用2024-01-01Java編程實(shí)現(xiàn)判斷網(wǎng)上鄰居文件是否存在的方法
這篇文章主要介紹了Java編程實(shí)現(xiàn)判斷網(wǎng)上鄰居文件是否存在的方法,涉及Java針對(duì)路徑轉(zhuǎn)換及字符串操作的相關(guān)技巧,需要的朋友可以參考下2015-10-10Springboot利用Aop捕捉注解實(shí)現(xiàn)業(yè)務(wù)異步執(zhí)行
在開發(fā)過程中,盡量會(huì)將比較耗時(shí)且并不會(huì)影響請(qǐng)求的響應(yīng)結(jié)果的業(yè)務(wù)放在異步線程池中進(jìn)行處理,那么到時(shí)什么任務(wù)在執(zhí)行的時(shí)候會(huì)創(chuàng)建單獨(dú)的線程進(jìn)行處理呢?這篇文章主要介紹了Springboot利用Aop捕捉注解實(shí)現(xiàn)業(yè)務(wù)異步執(zhí)行2023-04-04SpringBoot中實(shí)現(xiàn)啟動(dòng)任務(wù)的實(shí)現(xiàn)步驟
這篇文章主要介紹了SpringBoot中實(shí)現(xiàn)啟動(dòng)任務(wù)的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09java8 stream自定義分組求和并排序的實(shí)現(xiàn)
這篇文章主要介紹了java8 stream自定義分組求和并排序的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01