• 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 学习资料,欢迎扫码关注微信公众号:「平头哥的技术博文」领取,祝各位升职加薪。
    扫码关注

  • 相关阅读:
    javascript运动系列第二篇——变速运动
    深入学习jQuery动画控制
    深入学习jQuery动画队列
    深入学习jQuery自定义动画
    深入学习jQuery的三种常见动画效果
    深入学习jQuery鼠标事件
    深入学习jQuery事件对象
    深入学习jQuery事件绑定
    只想显示日期不想显示时间
    The conversion of a varchar data type to a datetime data type resulted in an out-of-range value
  • 原文地址:https://www.cnblogs.com/jamaler/p/11398149.html
Copyright © 2020-2023  润新知