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

Transactional注解導致Spring Bean定時任務失效的解決方法

 更新時間:2024年10月12日 11:56:24   作者:Butterfly(Papillon)  
這篇文章主要介紹了Transactional注解導致Spring Bean定時任務失效的解決方法,文中通過代碼示例介紹的非常詳細,對大家解決問題有一定的幫助,需要的朋友可以參考下

背景

業(yè)務需要定時撈取數(shù)據(jù)庫中新增的數(shù)據(jù)做數(shù)據(jù)處理及分析,更新狀態(tài),處理結束。而我們不能隨意定義線程池,規(guī)定使用統(tǒng)一的標準規(guī)范來定義線程池。如在配置文件中配置線程池的屬性:名稱,線程核心數(shù)等,任務屬性:任務名稱,任務處理類,延遲信息等等。定義好這些信息后,啟動系統(tǒng)時,線程池就會初始化并開始執(zhí)行任務。

業(yè)務實現(xiàn)

Spring監(jiān)聽器
使用Spring容器啟動結束發(fā)布的ApplicationReadyEvent事件來初始化線程池。

	@EventListener
    public void onApplicationReadyEvent(ApplicationReadyEvent event) {
        log.info("監(jiān)聽器啟動線程池。。。");
        jobManager.start();
    }

線程池統(tǒng)一處理類

public void start() {
       AbstractJob job = context.getAutowireCapableBeanFactory().createBean(BusinessJob.class);
       threadPool.scheduleWithFixedDelay(job, 1000, 1000, TimeUnit.MILLISECONDS);
   }

任務處理抽象類
所有任務都會繼承這個抽象類,它定義了一些公共的行為,比如看門狗監(jiān)視任務是否正常執(zhí)行。看門口屬性被定義為這個抽象類的屬性,它是直接導致任務失效的直接原因

    @Override
    public void run() {
        log.info("==========AbstractJob start===========");
        try {
            work();
            watchDog.print();
        } catch (Throwable t) {
            logger.log(Level.WARNING, "aaa bbb ccc", t);
        }
        log.info("==========AbstractJob end=============");
    }

    protected abstract void work();

任務處理類(繼承上面的抽象類)
該類被定義為Spring Bean對象

	@Override
    public void work() {
        log.info("job start.");
        handle();
        log.info("job end.");
    }
    
    public void handle(){
        // 處理業(yè)務
    }

新需求

由于某種原因業(yè)務提出新需求,而這個需求需要支持事務,于是根據(jù)以前學過的知識,直接在任務處理類中定義@Transactional注解的方法,通過Spring循環(huán)依賴,注入了自己。

	@Override
    public void work() {
        log.info("job start.");
        handle();
        // job
        job.testTransaction();
        log.info("job end.");
    }
	
	@Transactional
    public void testTransaction() {
        log.info("execute transaction.");
        jdbcTemplate.execute("update user set name='rick1' where id = 3");
//        jdbcTemplate.execute("insert into user values('1', 'rick')");
        log.info("execute transaction end.");
    }

本地測試發(fā)現(xiàn)執(zhí)行正常,提交代碼。
萬萬沒想到,測試反饋,定時任務只跑了一次就停止了,也沒有異常信息
也是本地重新啟動發(fā)現(xiàn)確實跑了一次任務就停了。于是將@Transactional注解干掉,任務正常的執(zhí)行。所以將事務方法重新定義一個類,加上@Component注解,通過bean對象引入到任務類中。
至此,業(yè)務是開發(fā)完了,但是出現(xiàn)這種問題的原因還沒有分析清楚,隨后就有了上面的demo復現(xiàn)問題。

猜測

@Transactional注解原理是生成一個代理對象包裹原生創(chuàng)建的Bean對象,是不是啟動時生成的代理對象將原來傳遞到線程池的任務被丟棄了。于是把所有涉及的源碼開始分析起來

獲取任務添加到線程池
從Spring容器中獲取的Bean對象是個代理對象,所以線程池里面執(zhí)行的任務是個代理對象

在這里插入圖片描述

ScheduledThreadPoolExecutor線程池
執(zhí)行scheduleWithFixedDelay()方法
檢驗
封裝任務
調用delayedExecute()方法執(zhí)行任務,最終調用ThreadPoolExecutor類ensurePrestart()方法,將任務提交到線程池執(zhí)行

在這里插入圖片描述

線程池啟動線程執(zhí)行的是ScheduledThreadPoolExecutor內部類的ScheduledFutureTask類run()方法

在這里插入圖片描述

第一次執(zhí)行任務時調用的是runAndReset()方法,如果任務執(zhí)行成功,則返回true,通過reExecutePeriodic()將任務重新添加到線程池去執(zhí)行;如果任務執(zhí)行失敗拋異常,則返回false,任務就被丟棄了,也就是跑一次,后面就不跑了。

在這里插入圖片描述

順著這個思路返回去看任務執(zhí)行過程,如果拋異常了,那就證明這個迷就解開了。c.call()就會調用我們定義的任務抽象類,它又會調用work()方法,而從日志得知work()正常執(zhí)行完成,所以問題極大可能出現(xiàn)在抽象類里面,work()執(zhí)行完了以后調用watchDog對象的方法,此時Debug發(fā)現(xiàn)watchDog對象為空,也就出現(xiàn)了空指針異常,這個異常會被捕獲,并打印出來,此時又離譜的事來了,任務類的代理對象的logger屬性又是空的,所以又出現(xiàn)了空指針異常拋出去了,導致任務停止執(zhí)行。

為什么代理對象的屬性都為空呢

Spring代理對象所有屬性都為空,只有被代理對象的屬性有值。

以上就是Transactional注解導致Spring Bean定時任務失效的解決方法的詳細內容,更多關于Transactional導致Spring Bean定時失效的資料請關注腳本之家其它相關文章!

相關文章

  • Java實現(xiàn)經(jīng)典游戲飛機大戰(zhàn)-I的示例代碼

    Java實現(xiàn)經(jīng)典游戲飛機大戰(zhàn)-I的示例代碼

    《飛機大戰(zhàn)-I》是一款融合了街機、競技等多種元素的經(jīng)典射擊手游。本文將利用java語言實現(xiàn)這游戲,文中采用了swing技術進行了界面化處理,感興趣的可以了解一下
    2022-02-02
  • java結合WebSphere MQ實現(xiàn)接收隊列文件功能

    java結合WebSphere MQ實現(xiàn)接收隊列文件功能

    WebSphereMQ,也稱MQSeries,以一致的、可靠的和易于管理的方式來連接應用程序,并為跨部門、企業(yè)范圍的集成提供了可靠的基礎。通過為重要的消息和事務提供可靠的、一次且僅一次的傳遞,MQ可以處理復雜的通信協(xié)議,并動態(tài)地將消息傳遞工作負載分配給可用的資源。
    2015-10-10
  • SpringCloud?Feign使用ApacheHttpClient代替默認client方式

    SpringCloud?Feign使用ApacheHttpClient代替默認client方式

    這篇文章主要介紹了SpringCloud?Feign使用ApacheHttpClient代替默認client方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 基于Spring實現(xiàn)搜索目錄下指定名稱文件

    基于Spring實現(xiàn)搜索目錄下指定名稱文件

    這篇文章主要為大家詳細介紹了如何基于Spring實現(xiàn)搜索目錄下指定名稱文件,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2025-08-08
  • java生成XML的方法【附demo源碼下載】

    java生成XML的方法【附demo源碼下載】

    這篇文章主要介紹了java生成XML的方法,涉及java針對xml格式文件的簡單操作技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下
    2016-12-12
  • SpringBoot配置ShedLock分布式定時任務

    SpringBoot配置ShedLock分布式定時任務

    ShedLock是一個在分布式環(huán)境中使用的定時任務框架,這篇文章主要介紹了SpringBoot配置ShedLock分布式定時任務,需要的朋友們下面隨著小編來一起學習學習吧
    2021-05-05
  • Java中位運算(移位、位與、或、異或、非) 的簡單實例

    Java中位運算(移位、位與、或、異或、非) 的簡單實例

    Java中位運算(移位、位與、或、異或、非) 的簡單實例,需要的朋友可以參考一下
    2013-02-02
  • SpringBoot項目引入token設置方式

    SpringBoot項目引入token設置方式

    本文詳細介紹了JWT(JSON Web Token)的基本概念、結構、應用場景以及工作原理,通過動手實踐,展示了如何在Spring Boot項目中實現(xiàn)JWT的生成、驗證和攔截器配置
    2025-01-01
  • 通過Maven下載依賴Jar包的流程分享

    通過Maven下載依賴Jar包的流程分享

    本文主要介紹了Maven下載依賴Jar包的詳細流程,包括輸入Maven倉庫的官方地址、搜索依賴Jar包、選擇版本、復制和粘貼Maven依賴到pom文件中下載依賴Jar包
    2025-02-02
  • MyBatis中的collection兩種使用方法及效率比較

    MyBatis中的collection兩種使用方法及效率比較

    collection主要是應對表關系是一對多的情況,本文主要介紹了MyBatis中的collection兩種使用方法及效率比較,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06

最新評論

湖南省| 高平市| 镇沅| 宜兰市| 通州区| 奉化市| 盐津县| 隆林| 东阳市| 东宁县| 台东县| 集贤县| 区。| 永登县| 高邮市| 江孜县| 云梦县| 禹城市| 阿拉善盟| 石台县| 来宾市| 济南市| 武定县| 丹巴县| 淮安市| 枣阳市| 桂东县| 洮南市| 新邵县| 西林县| 奎屯市| 中阳县| 泽普县| 南丹县| 涡阳县| 阳原县| 疏勒县| 英山县| 灵山县| 凤山市| 漯河市|