spring啟動加載程序的幾種方法介紹
關(guān)于在spring 容器初始化 bean 和銷毀前所做的操作定義方式有三種:
第一種:通過注解@PostConstruct 和 @PreDestroy 方法 實(shí)現(xiàn)初始化和銷毀bean之前進(jìn)行的操作
import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; public class DataInitializer{ @PostConstruct public void initMethod() throws Exception { System.out.println("initMethod 被執(zhí)行"); } @PreDestroy public void destroyMethod() throws Exception { System.out.println("destroyMethod 被執(zhí)行"); } }
第二種是:通過 在xml中定義init-method 和 destory-method方法
public class DataInitializer{ public void initMethod() throws Exception { System.out.println("initMethod 被執(zhí)行"); } public void destroyMethod() throws Exception { System.out.println("destroyMethod 被執(zhí)行"); } }
<bean id="dataInitializer" class="com.somnus.demo.DataInitializer" init-method="initMethod" destory-method="destroyMethod"/>
第三種是: 通過bean實(shí)現(xiàn)InitializingBean和 DisposableBean接口
import org.springframework.beans.factory.DisposableBean; public class DataInitializer implements InitializingBean,DisposableBean{ @Override public void afterPropertiesSet() throws Exception { System.out.println("afterPropertiesSet 被執(zhí)行"); } @Override public void destroy() throws Exception { System.out.println("destroy 被執(zhí)行"); } }
其中第一種和第二種是同一種形式,只不過一種xml配置,另外一種采用注解形式罷了,有很大區(qū)別的是第三種,如果同一個(gè)bean同時(shí)采用兩種方式初始化的時(shí)候執(zhí)行某個(gè)方法,首先在執(zhí)行順序上就會體現(xiàn)出來。
先執(zhí)行afterPropertiesSet(),后執(zhí)行initMethod()
這里我們看下源碼
這方式在spring中是怎么實(shí)現(xiàn)的?
通過查看spring的加載bean的源碼類(AbstractAutowireCapableBeanFactory)可看出其中奧妙
AbstractAutowireCapableBeanFactory類中的invokeInitMethods講解的非常清楚,源碼如下:
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { //判斷該bean是否實(shí)現(xiàn)了實(shí)現(xiàn)了InitializingBean接口,如果實(shí)現(xiàn)了InitializingBean接口,則只掉調(diào)用bean的afterPropertiesSet方法 boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { //直接調(diào)用afterPropertiesSet ((InitializingBean) bean).afterPropertiesSet(); return null; } },getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { //直接調(diào)用afterPropertiesSet ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null) { String initMethodName = mbd.getInitMethodName(); //判斷是否指定了init-method方法,如果指定了init-method方法,則再調(diào)用制定的init-method if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { //進(jìn)一步查看該方法的源碼,可以發(fā)現(xiàn)init-method方法中指定的方法是通過反射實(shí)現(xiàn) invokeCustomInitMethod(beanName, bean, mbd); } }
總結(jié):
1:spring為bean提供了兩種初始化bean的方式,實(shí)現(xiàn)InitializingBean接口,實(shí)現(xiàn)afterPropertiesSet方法,或者在配置文件中同過init-method指定,兩種方式可以同時(shí)使用
2:實(shí)現(xiàn)InitializingBean接口是直接調(diào)用afterPropertiesSet方法,比通過反射調(diào)用init-method指定的方法效率相對來說要高點(diǎn)。但是init-method方式消除了對spring的依賴
3:如果調(diào)用afterPropertiesSet方法時(shí)出錯(cuò),則不調(diào)用init-method指定的方法。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
springboot集成@DS注解實(shí)現(xiàn)數(shù)據(jù)源切換的方法示例
本文主要介紹了springboot集成@DS注解實(shí)現(xiàn)數(shù)據(jù)源切換的方法示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03mybatis主從表關(guān)聯(lián)查詢,返回對象帶有集合屬性解析
這篇文章主要介紹了mybatis主從表關(guān)聯(lián)查詢,返回對象帶有集合屬性解析,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03Json轉(zhuǎn)list二層解析轉(zhuǎn)換代碼實(shí)例
這篇文章主要介紹了Json轉(zhuǎn)list二層解析轉(zhuǎn)換代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12Open-Feign整合hystrix降級熔斷實(shí)戰(zhàn)記錄
這篇文章主要介紹了Open-Feign整合hystrix降級熔斷實(shí)戰(zhàn)記錄,本文通過實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09springboot統(tǒng)一接口返回?cái)?shù)據(jù)的實(shí)現(xiàn)
這篇文章主要介紹了springboot統(tǒng)一接口返回?cái)?shù)據(jù)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09SpringCloud Eureka 服務(wù)注冊實(shí)現(xiàn)過程
這篇文章主要介紹了SpringCloud Eureka 服務(wù)注冊實(shí)現(xiàn)過程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10