最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring中@PostConstruct的實(shí)現(xiàn)方法

 更新時間:2023年06月30日 10:25:20   作者:湘小寶666  
大多數(shù)java程序員都使用過@PostConstruct注解,它的作用就是在Bean初始化完成后執(zhí)行,相當(dāng)于我們常說的init()方法,但是我們看@PostConstruct只有單單的一個注解,它到底是如何實(shí)現(xiàn)在Bean初始化完成后就被調(diào)用的呢,本文將詳細(xì)給大家介紹一下

前言

大多數(shù)java程序員都使用過@PostConstruct注解,它的作用就是在Bean初始化完成后執(zhí)行,相當(dāng)于我們常說的init()方法。但是我們看@PostConstruct只有單單的一個注解,它到底是如何實(shí)現(xiàn)在Bean初始化完成后就被調(diào)用的呢?

源碼分析

我們通過idea搜索發(fā)現(xiàn),只有CommonAnnotationBeanPostProcessor這個類使用了@PostConstruct:

public?class?CommonAnnotationBeanPostProcessor?extends?InitDestroyAnnotationBeanPostProcessor?implementsInstantiationAwareBeanPostProcessor,?BeanFactoryAware,?Serializable?{
? ? ?public?CommonAnnotationBeanPostProcessor() {
? ? ? ?this.setOrder(2147483644);
? ? ? ?// 給initAnnotationType賦值
? ? ? ?this.setInitAnnotationType(PostConstruct.class);
? ? ? ?this.setDestroyAnnotationType(PreDestroy.class);
? ? ? ?this.ignoreResourceType("javax.xml.ws.WebServiceContext");
? ? ? ?if?(jndiPresent) {
? ? ? ? ? ?this.jndiFactory?=?new?SimpleJndiBeanFactory();
? ? ? }
?
? }
}

通過源碼發(fā)現(xiàn),這顯然就是一個BeanPostProcessor的子類啊,它在Spring的生命周期中起作用,所以我們可以重點(diǎn)關(guān)注postProcessBeforeInitialization()方法:

?public?Object?postProcessBeforeInitialization(Object?bean,?String?beanName)?throws?BeansException?{
? ? ? ?// 獲取被@PostConstruct注解的方法元數(shù)據(jù)
? ? ? ?InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata?metadata?=?this.findLifecycleMetadata(bean.getClass());
?
? ? ? ?try?{
? ? ? ? ? ?// 調(diào)用目標(biāo)方法
? ? ? ? ? ?metadata.invokeInitMethods(bean,?beanName);
? ? ? ? ? ?return?bean;
? ? ? }?catch?(InvocationTargetException?var5) {
? ? ? ? ? ?throw?new?BeanCreationException(beanName,?"Invocation of init method failed",?var5.getTargetException());
? ? ? }?catch?(Throwable?var6) {
? ? ? ? ? ?throw?new?BeanCreationException(beanName,?"Failed to invoke init method",?var6);
? ? ? }
? }

當(dāng)Bean初始化完成后,postProcessBeforeInitialization()方法將被調(diào)用,所有被注解了@PostConstruct都會被調(diào)用,無論這個方法是在父類還是子類中:

? ?private?InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata?findLifecycleMetadata(Class<?>?clazz) {
? ? ? ?// 如果緩存為null,那么構(gòu)建緩存;這個緩存是存儲Bean中所有被@PostConstruct注解的方法元數(shù)據(jù)
? ? ? ?if?(this.lifecycleMetadataCache?==?null) {
? ? ? ? ? ?// 構(gòu)建緩存
? ? ? ? ? ?return?this.buildLifecycleMetadata(clazz);
? ? ? }?else?{
? ? ? ? ?// 如果緩存不為null,那么從緩存中取出所有被@PostConstruct注解的方法元數(shù)據(jù)
? ? ? ? ? ?InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata?metadata?=(InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata)this.lifecycleMetadataCache.get(clazz);
? ? ? ? ?// 如果緩存中取出來的元數(shù)據(jù)為null,這段代碼這種寫法是考慮到現(xiàn)在有多個線程,用了加鎖操作保證只有一個線程去構(gòu)建緩存buildLifecycleMetadata()
? ? ? ? ? ?if?(metadata?==?null) {
? ? ? ? ? ? ? ?synchronized(this.lifecycleMetadataCache) {
? ? ? ? ? ? ? ? ? ?metadata?=?(InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata)this.lifecycleMetadataCache.get(clazz);
? ? ? ? ? ? ? ? ?// 如果此時還沒拿到元數(shù)據(jù),就去構(gòu)建緩存
? ? ? ? ? ? ? ? ? ?if?(metadata?==?null) {
? ? ? ? ? ? ? ? ? ? ? ?// 收集好元數(shù)據(jù)
? ? ? ? ? ? ? ? ? ? ? ?metadata?=?this.buildLifecycleMetadata(clazz);
? ? ? ? ? ? ? ? ? ? ? ?// 構(gòu)建緩存
? ? ? ? ? ? ? ? ? ? ? ?this.lifecycleMetadataCache.put(clazz,?metadata);
? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ?// 返回元數(shù)據(jù)
? ? ? ? ? ? ? ? ? ?return?metadata;
? ? ? ? ? ? ? }
? ? ? ? ? }?else?{
? ? ? ? ? ? ? ?// 返回元數(shù)據(jù)
? ? ? ? ? ? ? ?return?metadata;
? ? ? ? ? }
? ? ? }
? }

1.緩存為null的情況下直接構(gòu)建緩存;

2.緩存不為null,就從緩存中取被注解的方法元數(shù)據(jù),沒取到就構(gòu)建緩存;

所以我們重點(diǎn)看看緩存是如何構(gòu)建的:

? ?private?InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata?buildLifecycleMetadata(Class<?>?clazz) {
? ? ? ?// 如果這個類一定沒有被initAnnotationType或destroyAnnotationType注解
? ? ? ?// 此時initAnnotationType就是我們的@PostConstruct注解
? ? ? ?if?(!AnnotationUtils.isCandidateClass(clazz,?Arrays.asList(this.initAnnotationType,?this.destroyAnnotationType))) {
? ? ? ? ? ?return?this.emptyLifecycleMetadata;
? ? ? }?else?{
? ? ? ? ? ?// 準(zhǔn)備好列表來裝被注解的方法
? ? ? ? ? ?List<InitDestroyAnnotationBeanPostProcessor.LifecycleElement>?initMethods?=?new?ArrayList();
? ? ? ? ? ?List<InitDestroyAnnotationBeanPostProcessor.LifecycleElement>?destroyMethods?=?new?ArrayList();
? ? ? ? ? ?Class?targetClass?=?clazz;
? ? ? ? ? ?// 準(zhǔn)備循環(huán)向上遍歷所有的父類
? ? ? ? ? ?do?{
? ? ? ? ? ? ? ?List<InitDestroyAnnotationBeanPostProcessor.LifecycleElement>?currInitMethods?=?new?ArrayList();
? ? ? ? ? ? ? ?List<InitDestroyAnnotationBeanPostProcessor.LifecycleElement>?currDestroyMethods?=?new?ArrayList();
? ? ? ? ? ? ? ?ReflectionUtils.doWithLocalMethods(targetClass, (method)?->?{
? ? ? ? ? ? ? ? ? ?// 如果這個方法被@PostConstruct注解,那么就構(gòu)建元數(shù)據(jù)并放進(jìn)currInitMethods中
? ? ? ? ? ? ? ? ? ?if?(this.initAnnotationType?!=?null?&&?method.isAnnotationPresent(this.initAnnotationType)) {
? ? ? ? ? ? ? ? ? ? ? ?InitDestroyAnnotationBeanPostProcessor.LifecycleElement?element?=?newInitDestroyAnnotationBeanPostProcessor.LifecycleElement(method);
? ? ? ? ? ? ? ? ? ? ? ?currInitMethods.add(element);
? ? ? ? ? ? ? ? ? ? ? ?if?(this.logger.isTraceEnabled()) {
? ? ? ? ? ? ? ? ? ? ? ? ? ?this.logger.trace("Found init method on class ["?+?clazz.getName()?+?"]: "?+?method);
? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ?// 下面是判斷是否被destroyAnnotationType注解
? ? ? ? ? ? ? ? ? ?if?(this.destroyAnnotationType?!=?null?&&?method.isAnnotationPresent(this.destroyAnnotationType)) {
? ? ? ? ? ? ? ? ? ? ? ?currDestroyMethods.add(new?InitDestroyAnnotationBeanPostProcessor.LifecycleElement(method));
? ? ? ? ? ? ? ? ? ? ? ?if?(this.logger.isTraceEnabled()) {
? ? ? ? ? ? ? ? ? ? ? ? ? ?this.logger.trace("Found destroy method on class ["?+?clazz.getName()?+?"]: "?+?method);
? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? }
?
? ? ? ? ? ? ? });
? ? ? ? ? ? ? ?// 先把當(dāng)前類被注解的方法元數(shù)據(jù)列表放進(jìn)initMethods頭部
? ? ? ? ? ? ? ?initMethods.addAll(0,?currInitMethods);
? ? ? ? ? ? ? ?destroyMethods.addAll(currDestroyMethods);
? ? ? ? ? ? ? ?// 獲取當(dāng)前類的父類
? ? ? ? ? ? ? ?targetClass?=?targetClass.getSuperclass();
? ? ? ? ? ? ?// 準(zhǔn)備遍歷父類是否有被注解的方法,有的話收集好放進(jìn)initMethods頭部
? ? ? ? ? }?while(targetClass?!=?null?&&?targetClass?!=?Object.class);
? ? ? ? ?// 返回構(gòu)建好的元數(shù)據(jù)
? ? ? ? ? ?return?initMethods.isEmpty()?&&?destroyMethods.isEmpty()???this.emptyLifecycleMetadata?:?newInitDestroyAnnotationBeanPostProcessor.LifecycleMetadata(clazz,?initMethods,?destroyMethods);
? ? ? }
? }

所以我們通過上述源碼的分析,最后得出以下結(jié)論:

1.Bean的父類方法也可以使用@PostConstruct注解;

2.執(zhí)行的時候是先執(zhí)行被@PostConstruct注解的父類方法,再執(zhí)行被@PostConstruct注解的子類方法;

3.被@PostConstruct注解的方法不能有任何參數(shù),可以通過new InitDestroyAnnotationBeanPostProcessor.LifecycleElement(method)源碼驗(yàn)證;

以上就是Spring中@PostConstruct的實(shí)現(xiàn)方法的詳細(xì)內(nèi)容,更多關(guān)于Spring @PostConstruct實(shí)現(xiàn)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • spring boot項(xiàng)目如何采用war在tomcat容器中運(yùn)行

    spring boot項(xiàng)目如何采用war在tomcat容器中運(yùn)行

    這篇文章主要介紹了spring boot項(xiàng)目如何采用war在tomcat容器中運(yùn)行呢,主要講述將SpringBoot打成war包并放入tomcat中運(yùn)行的方法分享,需要的朋友可以參考下
    2022-11-11
  • Java中List.sort()自定義排序規(guī)則幾種方式

    Java中List.sort()自定義排序規(guī)則幾種方式

    Java中可通過Comparator匿名類、Lambda表達(dá)式、靜態(tài)方法、自定義對象及實(shí)現(xiàn)Comparable接口實(shí)現(xiàn)List排序,這篇文章主要介紹了Java中List.sort()自定義排序規(guī)則幾種方式,需要的朋友可以參考下
    2025-06-06
  • jfreechart畫折線圖的方法

    jfreechart畫折線圖的方法

    這篇文章主要為大家詳細(xì)介紹了jfreechart畫折線圖的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • Java8與Scala中的Lambda表達(dá)式深入講解

    Java8與Scala中的Lambda表達(dá)式深入講解

    這篇文章主要給大家介紹了關(guān)于Java8與Scala中Lambda表達(dá)式的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • 全面解析Java中常見Exception異常的錯誤排查與代碼修正

    全面解析Java中常見Exception異常的錯誤排查與代碼修正

    這篇文章主要為大家詳細(xì)介紹了Java開發(fā)中最常見的異常類型及其處理方法,包括運(yùn)行時異常(如NullPointerException,ArrayIndexOutOfBoundsException)和受檢異常,下面小編就和大家詳細(xì)介紹一下吧
    2026-03-03
  • java中XML的使用全過程

    java中XML的使用全過程

    這篇文章主要介紹了java中XML的使用全過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • AsyncHttpClient的默認(rèn)配置源碼流程解讀

    AsyncHttpClient的默認(rèn)配置源碼流程解讀

    這篇文章主要為大家介紹了AsyncHttpClient的默認(rèn)配置源碼流程解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Java中隨機(jī)函數(shù)變換的示例詳解

    Java中隨機(jī)函數(shù)變換的示例詳解

    這篇文章主要為大家詳細(xì)介紹了Java中隨機(jī)函數(shù)的變換,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Java有一定的幫助,感興趣的可以了解一下
    2022-08-08
  • 深入理解Spring MVC的數(shù)據(jù)轉(zhuǎn)換

    深入理解Spring MVC的數(shù)據(jù)轉(zhuǎn)換

    這篇文章主要給大家介紹了關(guān)于Spring MVC數(shù)據(jù)轉(zhuǎn)換的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起看看吧。
    2017-09-09
  • mybatis模糊查詢like語句該如何寫

    mybatis模糊查詢like語句該如何寫

    MyBatis模糊查詢通常使用LIKE關(guān)鍵字,結(jié)合concat函數(shù)拼接通配符%實(shí)現(xiàn),在MyBatis配置文件中,通過#{keyword}傳遞參數(shù),生成帶有通配符的查詢語句,MyBatis-Plus中,通過LambdaQueryWrapper類和like方法構(gòu)建模糊查詢條件,簡化查詢操作
    2024-09-09

最新評論

关岭| 长宁县| 临潭县| 德化县| 吴旗县| 新丰县| 渑池县| 鹿邑县| 怀宁县| 仙桃市| 周口市| 闵行区| 华蓥市| 贵溪市| 松溪县| 衢州市| 双鸭山市| 合山市| 永胜县| 稻城县| 高邮市| 和林格尔县| 海伦市| 韩城市| 揭阳市| 平阳县| 名山县| 福清市| 策勒县| 南江县| 柏乡县| 卢湾区| 东明县| 元氏县| 福海县| 西华县| 白河县| 宝清县| 新宁县| 库车县| 新疆|