一文詳解spring注解配置bean的初始化方法和銷毀方法
本篇我們講解下spring項(xiàng)目中如何為bean指定初始化方法和銷毀方法。當(dāng)spring完成bean的屬性賦值之后,就會(huì)執(zhí)行bean的初始化方法,而當(dāng)spring要銷毀bean實(shí)例的時(shí)候,也會(huì)調(diào)用bean的銷毀方法。我們可以在初始化方法中做一些資源加載的操作,比如緩存數(shù)據(jù)到redis。而在銷毀方法中,可以做一些資源釋放的操作,比如刪除redis緩存數(shù)據(jù)、釋放數(shù)據(jù)庫連接等。由于我們現(xiàn)在很少寫spring的xml文件,所以這次就講解通過注解的方式來指定bean的初始化方法和銷毀方法。我們先定義如下的配置類、業(yè)務(wù)服務(wù)類和單元測試方法,供后面測試使用。
package?com.xk.spring.init; import?org.springframework.context.annotation.Bean; import?org.springframework.context.annotation.Configuration; /**?測試初始化方法和銷毀方法 ?* ?*?@author?xk ?*?@since?2023.04.30?15:31 ?*/ @Configuration public?class?InitConfig?{ ????@Bean ????public?RedisService?redisService(){ ????????return?new?RedisService(); ????} }
package?com.xk.spring.init; /** ?*?用于如何配置講解bean的初始化方法 ?*?@author?xk ?*?@since?2023.04.30?15:26 ?*/ public?class?RedisService{ ????public?RedisService(){ ????????System.out.println("這是RedisService構(gòu)造方法"); ????} }
單元測試方法如下:
????@Test ????public?void?testInitAndDestroyConfig(){ ????????AnnotationConfigApplicationContext?applicationContext?=?new?AnnotationConfigApplicationContext(InitConfig.class); ????????applicationContext.close(); ????}
1、配置bean的初始化方法
1.1、使用@Bean注解的initMethod屬性
我們在配置類中使用@Bean注解生成bean實(shí)例的時(shí)候,可以使用@Bean注解的initMethod屬性指定初始化方法,initMethod的值是目標(biāo)bean對應(yīng)的類中的方法名,當(dāng)spring完成bean的屬性賦值之后,就會(huì)執(zhí)行initMethod對應(yīng)的這個(gè)方法。
修改RedisService服務(wù)類內(nèi)容如下,增加自定義的initMethod方法:
package?com.xk.spring.init; /** ?*?用于如何配置講解bean的初始化方法 ?*?@author?xk ?*?@since?2023.04.30?15:26 ?*/ public?class?RedisService?{ ????public?RedisService(){ ????????System.out.println("這是RedisService構(gòu)造方法"); ????} ????public?void?initMethod(){ ????????System.out.println("(1)這是一個(gè)@Bean?initMethod初始化方法"); ????} }
修改InitConfig配置類如下,指定@Bean注解的initMethod屬性值為RedisService類中的initMethod方法:
package?com.xk.spring.init; import?org.springframework.context.annotation.Bean; import?org.springframework.context.annotation.Configuration; /**?測試初始化方法和銷毀方法 ?* ?*?@author?xk ?*?@since?2023.04.30?15:31 ?*/ @Configuration public?class?InitConfig?{ ????@Bean(initMethod?=?"initMethod") ????public?RedisService?redisService(){ ????????return?new?RedisService(); ????} }
最后執(zhí)行testInitAndDestroyConfig單元測試方法,得出如下結(jié)果:
這是RedisService構(gòu)造方法 (1)這是一個(gè)@Bean?initMethod初始化方法
1.2、使用@PostConstruct注解
@PostConstruct注解用于在bean完成依賴注入(屬性賦值)之后需要執(zhí)行的方法上,它是被用在bean對應(yīng)的類中定義的方法,而且一個(gè)類中只能有一個(gè)方法被標(biāo)記@PostConstruct注解。只要方法所屬的類不是攔截器類而且方法本身無參且沒有返回值,那就可以在這個(gè)方法上面使用@PostConstruct注解。(如果方法所屬類的是攔截器類,在滿足一定的要求時(shí)也可以使用@PostConstruct注解,但這種情況很少使用,所以此處先不提。)我們保持InitConfig類不變,修改RedisService類內(nèi)容如下:
package?com.xk.spring.init; import?javax.annotation.PostConstruct; /** ?*?用于如何配置講解bean的初始化方法 ?*?@author?xk ?*?@since?2023.04.30?15:26 ?*/ public?class?RedisService{ ????public?RedisService(){ ????????System.out.println("這是RedisService構(gòu)造方法"); ????} ????public?void?initMethod(){ ????????System.out.println("(1)這是一個(gè)@Bean?initMethod初始化方法"); ????} ???? ????@PostConstruct ????private?void?initMethod2(){ ????????System.out.println("(2)這是一個(gè)@PostConstruct初始化方法"); ????} }
最后執(zhí)行testInitAndDestroyConfig單元測試方法,得出如下結(jié)果:
這是RedisService構(gòu)造方法 (2)這是一個(gè)@PostConstruct初始化方法 (1)這是一個(gè)@Bean?initMethod初始化方法
可以看出,標(biāo)記@PostConstruct注解的方法要比@Bean注解的InitMethod屬性指定的方法先執(zhí)行。
1.3、實(shí)現(xiàn)InitializingBean接口
InitializingBean接口只有一個(gè)afterPropertiesSet方法,假如一個(gè)bean完成了屬性賦值,并且這個(gè)bean對應(yīng)的類實(shí)現(xiàn)了該接口,spring就會(huì)調(diào)用afterPropertiesSet方法。我們繼續(xù)在前兩步的基礎(chǔ)上進(jìn)行修改,保持InitConfig類不變,修改RedisService類如下:
package?com.xk.spring.init; import?org.springframework.beans.factory.InitializingBean; import?javax.annotation.PostConstruct; /** ?*?用于如何配置講解bean的初始化方法 ?*?@author?xk ?*?@since?2023.04.30?15:26 ?*/ public?class?RedisService?implements?InitializingBean?{ ????public?RedisService(){ ????????System.out.println("這是RedisService構(gòu)造方法"); ????} ????public?void?initMethod(){ ????????System.out.println("(1)這是一個(gè)@Bean?initMethod初始化方法"); ????} ????@PostConstruct ????private?void?initMethod2(){ ????????System.out.println("(2)這是一個(gè)@PostConstruct初始化方法"); ????} ????@Override ????public?void?afterPropertiesSet()?throws?Exception?{ ????????System.out.println("(3)這是一個(gè)InitializingBean初始化方法"); ????} }
最后執(zhí)行單元測試,得出結(jié)果如下:
這是RedisService構(gòu)造方法 (2)這是一個(gè)@PostConstruct初始化方法 (3)這是一個(gè)InitializingBean初始化方法 (1)這是一個(gè)@Bean?initMethod初始化方法
1.4、總結(jié)
bean的初始化方法調(diào)用位于bean的屬性賦值之后,我們可以同時(shí)使用以上三種方式來指定bean的初始化方法,而且執(zhí)行順序如下:
@PostConstruct指定的方法-->InitializingBean接口的afterPropertiesSet方法-->@Bean的initMethod屬性指定的方法
2、配置bean的銷毀方法
2.1、使用@Bean注解的destroyMethod屬性
我們在配置類中使用@Bean注解生成bean實(shí)例的時(shí)候,可以使用@Bean注解的destroyMethod屬性指定bean的銷毀方法,destroyMethod的值是目標(biāo)bean對應(yīng)的類中的方法名,當(dāng)spring完成bean的屬性賦值之后,就會(huì)執(zhí)行destroyMethod對應(yīng)的這個(gè)方法。
我們修改RedisService服務(wù)類內(nèi)容如下,增加自定義的destroyMethod方法:
package?com.xk.spring.init; import?org.springframework.beans.factory.InitializingBean; import?javax.annotation.PostConstruct; /** ?*?用于如何配置講解bean的初始化方法 ?*?@author?xk ?*?@since?2023.04.30?15:26 ?*/ public?class?RedisService?implements?InitializingBean?{ ????public?RedisService(){ ????????System.out.println("這是RedisService構(gòu)造方法"); ????} ????public?void?initMethod(){ ????????System.out.println("(1)這是一個(gè)@Bean?initMethod初始化方法"); ????} ????@PostConstruct ????private?void?initMethod2(){ ????????System.out.println("(2)這是一個(gè)@PostConstruct初始化方法"); ????} ????@Override ????public?void?afterPropertiesSet()?throws?Exception?{ ????????System.out.println("(3)這是一個(gè)InitializingBean初始化方法"); ????} ????public?void?destroyMethod(){ ????????System.out.println("(1)這是一個(gè)@Bean?destroyMethod銷毀方法"); ????} }
修改InitConfig配置類如下,指定@Bean注解的destroyMethod屬性值為RedisService類中的destroyMethod方法:
package?com.xk.spring.init; import?org.springframework.context.annotation.Bean; import?org.springframework.context.annotation.Configuration; /**?測試初始化方法和銷毀方法 ?* ?*?@author?xk ?*?@since?2023.04.30?15:31 ?*/ @Configuration public?class?InitConfig?{ ????@Bean(initMethod?=?"initMethod",destroyMethod?=?"destroyMethod") ????public?RedisService?redisService(){ ????????return?new?RedisService(); ????} }
最后執(zhí)行testInitAndDestroyConfig單元測試方法,得出如下結(jié)果:
這是RedisService構(gòu)造方法 (2)這是一個(gè)@PostConstruct初始化方法 (3)這是一個(gè)InitializingBean初始化方法 (1)這是一個(gè)@Bean?initMethod初始化方法 (1)這是一個(gè)@Bean?destroyMethod銷毀方法
2.2、使用@PreDestroy注解
@PreDestroy注解用于在bean被銷毀時(shí)需要執(zhí)行的方法上,它是被用在bean對應(yīng)的類中定義的方法,而且一個(gè)類中只能有一個(gè)方法被標(biāo)記@PreDestroy注解。只要方法所屬的類不是攔截器類而且方法本身無參且沒有返回值,那就可以在這個(gè)方法上面使用@PreDestroy注解。(如果方法所屬類的是攔截器類,在滿足一定的要求時(shí)也可以使用@PreDestroyt注解,但這種情況很少使用,所以此處先不提。)我們保持InitConfig類不變,修改RedisService類內(nèi)容如下:
package?com.xk.spring.init; import?org.springframework.beans.factory.DisposableBean; import?org.springframework.beans.factory.InitializingBean; import?javax.annotation.PostConstruct; import?javax.annotation.PreDestroy; /** ?*?用于如何配置講解bean的初始化方法 ?*?@author?xk ?*?@since?2023.04.30?15:26 ?*/ public?class?RedisService?implements?InitializingBean,?DisposableBean?{ ????public?RedisService(){ ????????System.out.println("這是RedisService構(gòu)造方法"); ????} ????public?void?initMethod(){ ????????System.out.println("(1)這是一個(gè)@Bean?initMethod初始化方法"); ????} ????@PostConstruct ????private?void?initMethod2(){ ????????System.out.println("(2)這是一個(gè)@PostConstruct初始化方法"); ????} ????@Override ????public?void?afterPropertiesSet()?throws?Exception?{ ????????System.out.println("(3)這是一個(gè)InitializingBean初始化方法"); ????} ????public?void?destroyMethod(){ ????????System.out.println("(1)這是一個(gè)@Bean?destroyMethod銷毀方法"); ????} ????@PreDestroy ????public?void?destroyMethod2()?{ ????????System.out.println("(2)這是一個(gè)@PreDestroy銷毀方法"); ????} }
最后執(zhí)行testInitAndDestroyConfig單元測試方法,得出如下結(jié)果:
這是RedisService構(gòu)造方法 (2)這是一個(gè)@PostConstruct初始化方法 (3)這是一個(gè)InitializingBean初始化方法 (1)這是一個(gè)@Bean?initMethod初始化方法 (2)這是一個(gè)@PreDestroy銷毀方法 (1)這是一個(gè)@Bean?destroyMethod銷毀方法
可以看出,標(biāo)記@PreDestroy注解的方法要比@Bean注解的destroyMethod屬性指定的方法先執(zhí)行。
2.3、實(shí)現(xiàn)DisposableBean接口
DisposableBean接口只有一個(gè)destroy方法,假如一個(gè)bean對應(yīng)的類實(shí)現(xiàn)了該接口,spring在bean(或容器)銷毀時(shí)就會(huì)調(diào)用destroy方法。我們繼續(xù)在前面代碼的基礎(chǔ)上進(jìn)行修改,保持InitConfig類不變,修改RedisService類如下:
package?com.xk.spring.init; import?org.springframework.beans.factory.DisposableBean; import?org.springframework.beans.factory.InitializingBean; import?javax.annotation.PostConstruct; import?javax.annotation.PreDestroy; /** ?*?用于如何配置講解bean的初始化方法 ?*?@author?xk ?*?@since?2023.04.30?15:26 ?*/ public?class?RedisService?implements?InitializingBean,?DisposableBean?{ ????public?RedisService(){ ????????System.out.println("這是RedisService構(gòu)造方法"); ????} ????public?void?initMethod(){ ????????System.out.println("(1)這是一個(gè)@Bean?initMethod初始化方法"); ????} ????@PostConstruct ????private?void?initMethod2(){ ????????System.out.println("(2)這是一個(gè)@PostConstruct初始化方法"); ????} ????@Override ????public?void?afterPropertiesSet()?throws?Exception?{ ????????System.out.println("(3)這是一個(gè)InitializingBean初始化方法"); ????} ????public?void?destroyMethod(){ ????????System.out.println("(1)這是一個(gè)@Bean?destroyMethod銷毀方法"); ????} ????@PreDestroy ????public?void?destroyMethod2()?{ ????????System.out.println("(2)這是一個(gè)@PreDestroy銷毀方法"); ????} ????@Override ????public?void?destroy()?throws?Exception?{ ????????System.out.println("(3)這是一個(gè)DisposableBean銷毀方法"); ????} }
最后執(zhí)行單元測試,得出結(jié)果如下:
這是RedisService構(gòu)造方法 (2)這是一個(gè)@PostConstruct初始化方法 (3)這是一個(gè)InitializingBean初始化方法 (1)這是一個(gè)@Bean?initMethod初始化方法 (2)這是一個(gè)@PreDestroy銷毀方法 (3)這是一個(gè)DisposableBean銷毀方法 (1)這是一個(gè)@Bean?destroyMethod銷毀方法
2.4、總結(jié)
bean的銷毀方法調(diào)用位于bean(或容器)被銷毀的時(shí)候,我們可以同時(shí)使用以上三種方式來指定bean的銷毀方法,而且執(zhí)行順序如下:
@PreDestroy指定的方法-->DisposableBean接口的destroy方法-->@Bean的destroyMethod屬性指定的方法
以上就是一文詳解spring注解配置bean的初始化方法和銷毀方法的詳細(xì)內(nèi)容,更多關(guān)于spring注解配置bean初始化方法和銷毀方法的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java實(shí)現(xiàn)表格數(shù)據(jù)的存儲(chǔ)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)表格數(shù)據(jù)的存儲(chǔ),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04Java避免UTF-8的csv文件打開中文出現(xiàn)亂碼的方法
這篇文章主要介紹了Java避免UTF-8的csv文件打開中文出現(xiàn)亂碼的方法,結(jié)合實(shí)例形式分析了java操作csv文件時(shí)使用utf-16le編碼與utf8編碼相關(guān)操作技巧,需要的朋友可以參考下2019-07-07Java實(shí)現(xiàn)圖片倒影的源碼實(shí)例內(nèi)容
在本篇文章里小編給大家整理的是關(guān)于Java實(shí)現(xiàn)圖片倒影的源碼以及相關(guān)知識點(diǎn),有需要的朋友們學(xué)習(xí)下。2019-09-09利用SpringMVC接收復(fù)雜對象和多個(gè)文件(前端使用JQuery)
這篇文章主要介紹了利用SpringMVC接收復(fù)雜對象和多個(gè)文件(前端使用JQuery),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10Java8?stream流分組groupingBy的使用方法代碼
對于java8的新特性groupingBy方法,相信有很多人都在工作中用過,這篇文章主要給大家介紹了關(guān)于Java8?stream流分組groupingBy的使用方法,需要的朋友可以參考下2024-01-01