事务不生效之this调用

4 篇文章 0 订阅

在业务开发中,我们在一个类中一个服务方法调用同一个类服务方法,发现事务失效,代码如下:

比如一个订单入库:

public class OrderService implements IOrderService {

    @Override
    @Transactional
    public Boolean initOrder() {
        //初始主订单

        return Boolean.TRUE;
    }
    private Boolean initProdcut(Long productId) {
        //初始化订单对应得商品
        return Boolean.TRUE;
    }
}

方法initProduct事务不生效,出现场景如上。

首先通过分析事务不生效步骤如下:

1、检查存储引擎是否是innodb。

2、检查项目中事务是否生效,检查项目是否正确开启事务。

3、检查配置是否配置正确,主要检查:@Transactional 注解的 rollbackFor 捕获的异常范围小于代码抛出的异常,导致不会滚; 设置了事务的timeout时间,代码逻辑执行超时了,导致事务失效
;被@Transactional 注解修饰的方法, 修饰符非public 或者被final修饰. Aop没办法为其生成一个代理。

4、项目是否存在this调用。

通过分析以前属于第4点;那我通过JDK动态代理实现代码来分析为什么不会生效。通过新增用户的同时检查用户同时在打印调用方法日志,代码如下。

用户操作接口:

public interface IUserService {
    /**
     * 新增用户
     * @return
     */
    public  Integer addUser();
    /**
     * 检查用户信息
     * @return
     */
    public  Boolean checkUser();
}

操作用户实现:

public class UserService implements IUserService {


     @Override
    public Integer addUser() {
        System.out.println("新增用户");
        this.checkUser();
        return 0;
    }

    @Override
    public Boolean checkUser() {
        System.out.println("检查用户");
        return Boolean.TRUE;
    }
}

日志处理器:

public class LogHanler implements InvocationHandler {

    private Object object;

    public LogHanler(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(String.format("调用方法开始:[%s] ", method.getName()));

        Object result = method.invoke(object, args);  // 调用 target 的 method 方法
        System.out.println(String.format("调用方法结束[%s] ", method.getName()));
        return result;

    }
}

运行:

    public static void main(String[] args) {
        UserService userService = new UserService();
        LogHanler logHanler = new LogHanler(userService);
        ClassLoader classLoader = userService.getClass().getClassLoader();
        IUserService o = (IUserService)Proxy.newProxyInstance(classLoader, userService.getClass().getInterfaces(), logHanler);
        o.addUser();
    }

运行结果如下:

调用方法开始:[addUser] 
新增用户
检查用户
调用方法结束[addUser] 

        细心的朋友会发现没有打印调用方法checkUser。我在调整一下代码,我把动态代码类传入到UserService 服务中。同时我在IUserService 接口中新增 setUserService ,代码调整如下:

用户操作接口:

public interface IUserService {
    /**
     * 新增用户
     * @return
     */
    public  Integer addUser();
    /**
     * 检查用户信息
     * @return
     */
    public  Boolean checkUser();
}

操作用户实现:

public class UserService implements IUserService {

    private IUserService userService;

     @Override
    public Integer addUser() {
        System.out.println("新增用户");
        userService.checkUser();
        return 0;
    }

    @Override
    public Boolean checkUser() {
        System.out.println("检查用户");
        return Boolean.TRUE;
    }
}

运行代码调整:

    public static void main(String[] args) {
        UserService userService = new UserService();
        LogHanler logHanler = new LogHanler(userService);
        ClassLoader classLoader = userService.getClass().getClassLoader();
        IUserService o = (IUserService)Proxy.newProxyInstance(classLoader, userService.getClass().getInterfaces(), logHanler);
        userService.setUserService(o);
        o.addUser();
    }

运行结果如下:

调用方法开始:[setUserService] 
调用方法结束[setUserService] 
调用方法开始:[addUser] 
新增用户
调用方法开始:[checkUser] 
检查用户
调用方法结束[checkUser] 
调用方法结束[addUser] 

        结果与我们预期调用顺序一样,checkUser被调用了。其实在我只是把调用实例传到UserService服务中。我们同时在调用addUser时使用了我传入的代理示例调用checkUser方法,之前使用的this调用。

         总结:AOP在代理是同类方法使用this就没有走动态代理实现,导致事务不会生效。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值