SpringBoot 內部方法調用,事務不起作用的原因及解決辦法


在做業務開發時,遇到了一個事務不起作用的問題。大概流程是這樣的,方法內部的定時任務調用了一個帶事務的方法,失敗后事務沒有回滾。查閱資料后,問題得到解決,記錄下來分享給大家。

場景

我在這里模擬一個場景,大概的調用方式就如下面的代碼這樣。


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void insertUser(User user) {
        userMapper.insertUser(user);
        throw new RuntimeException("");
    }
    
    /**
     * 內部調用新增方法
     *
     * @param user
     */
    @Override
    public void invokeInsertUser(User user) {
        this.insertUser(user);
    }

原因

AOP使用的是動態代理的機制,它會給類生成一個代理類,事務的相關操作都在代理類上完成。內部方式使用this調用方式時,使用的是實例調用,並沒有通過代理類調用方法,所以會導致事務失效。

解決辦法

方法一 引入自身bean

在類內部通過@Autowired將本身bean引入,然后通過調用自身bean,從而實現使用AOP代理操作。

注入自身bean

    @Autowired
    @Lazy
    private UserService service;

修改invokeInsertUser方法

    /**
     * 解決方法一 在bean中將自己注入進來
     * @param user
     */
    @Override
    public void invokeInsertUser(User user) {
        this.service.insertUser(user);
    }

方法二 通過ApplicationContext引入bean

通過ApplicationContext獲取bean,通過bean調用內部方法,就使用了bean的代理類。

注入ApplicationContext

    @Autowired
    ApplicationContext applicationContext;

修改invokeInsertUser方法

    /**
     * 解決方法二 通過applicationContext獲取到bean
     * @param user
     */
    @Override
    public void invokeInsertUser(User user) {
        ((UserService)applicationContext.getBean("userService")).invokeInsertUser(user);
    }

方法三 通過AopContext獲取當前類的代理類

通過AopContext獲取當前類的代理類,直接通過代理類調用方法

在引導類上添加@EnableAspectJAutoProxy(exposeProxy=true)注解

修改invokeInsertUser方法

    /**
     * 解決方法三 通過applicationContext獲取到bean
     *
     * @param user
     */
    @Override
    public void invokeInsertUser(User user) {
        ((UserService) AopContext.currentProxy()).invokeInsertUser(user);
    }

以上就是內部方法調用時,事務不起作用的原因及解決辦法。

最后

打個小廣告,金九銀十跳槽季,平頭哥給大家整理了一份較全面的 Java 學習資料,歡迎掃碼關注微信公眾號:「平頭哥的技術博文」領取,祝各位升職加薪。
掃碼關注


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM