欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

背景

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

業(yè)務實現

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

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

線程池統一處理類

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

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

    @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è)務提出新需求,而這個需求需要支持事務,于是根據以前學過的知識,直接在任務處理類中定義@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ā)現執(zhí)行正常,提交代碼。
萬萬沒想到,測試反饋,定時任務只跑了一次就停止了,也沒有異常信息
也是本地重新啟動發(fā)現確實跑了一次任務就停了。于是將@Transactional注解干掉,任務正常的執(zhí)行。所以將事務方法重新定義一個類,加上@Component注解,通過bean對象引入到任務類中。
至此,業(yè)務是開發(fā)完了,但是出現這種問題的原因還沒有分析清楚,隨后就有了上面的demo復現問題。

猜測

@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í)行完成,所以問題極大可能出現在抽象類里面,work()執(zhí)行完了以后調用watchDog對象的方法,此時Debug發(fā)現watchDog對象為空,也就出現了空指針異常,這個異常會被捕獲,并打印出來,此時又離譜的事來了,任務類的代理對象的logger屬性又是空的,所以又出現了空指針異常拋出去了,導致任務停止執(zhí)行。

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

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

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

相關文章

  • Java集合List和Map互轉的方法總結

    Java集合List和Map互轉的方法總結

    有時候我們需要將給定的List轉換為Map,或者Map轉換為List,本文主要介紹了Java集合List和Map互轉的方法總結,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • Maven3種打包方式中maven-assembly-plugin的使用詳解

    Maven3種打包方式中maven-assembly-plugin的使用詳解

    這篇文章主要介紹了Maven3種打包方式中maven-assembly-plugin的使用,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • Java如何接收XML格式參數并轉換為JSON

    Java如何接收XML格式參數并轉換為JSON

    在 Java 應用程序中,處理 XML 數據并將其轉換為 JSON 格式是很常見的任務,這篇文章為大家整理了一下具體的實現方法,希望對大家有所幫助
    2025-03-03
  • 解析SpringBoot @EnableAutoConfiguration的使用

    解析SpringBoot @EnableAutoConfiguration的使用

    這篇文章主要介紹了解析SpringBoot @EnableAutoConfiguration的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • 簡述IDEA集成Git在實際項目中的運用

    簡述IDEA集成Git在實際項目中的運用

    這篇文章主要介紹了IDEA集成Git在實際項目中的運用,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-07-07
  • JDK1.6“新“特性Instrumentation之JavaAgent(推薦)

    JDK1.6“新“特性Instrumentation之JavaAgent(推薦)

    這篇文章主要介紹了JDK1.6“新“特性Instrumentation之JavaAgent,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • SpringBoot3和mybatis-plus整合出現的問題解決辦法

    SpringBoot3和mybatis-plus整合出現的問題解決辦法

    SpringBoot和MybatisPlus的整合可以讓我們更加方便地進行數據庫操作,這篇文章主要給大家介紹了關于SpringBoot3和mybatisplus整合出現的一些問題的相關資料,需要的朋友可以參考下
    2024-01-01
  • Java在Word中添加多行圖片水印

    Java在Word中添加多行圖片水印

    這篇文章主要介紹了Java在Word中添加多行圖片,圖文講解的很清晰,有對于這方面不懂得同學可以跟著研究下
    2021-02-02
  • SpringBoot3.3.X整合Mybatis-Plus的實現示例

    SpringBoot3.3.X整合Mybatis-Plus的實現示例

    本文介紹了在Spring Boot 3.3.2中整合MyBatis-Plus 3.5.7,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-03-03
  • SpringBoot與Spring中數據緩存Cache超詳細講解

    SpringBoot與Spring中數據緩存Cache超詳細講解

    我們知道內存讀取速度遠大于硬盤讀取速度,當需要重復獲取相同數據時,一次一次的請求數據庫或者遠程服務,導致在數據庫查詢或者遠程方法調用上小號大量的時間,最終導致程序性能降低,這就是數據緩存要解決的問題,學過計算機組成原理或者操作系統的同學們應該比較熟悉
    2022-10-10

最新評論