@transactional注解_为啥同一个类中普通方法调用Spring注解方法,注解会失效?看完你就明白,So easy!...

v2-ad99721921006a9d3e61c4db9193eb32_1440w.jpg?source=172ae18b

Spring注解(如@Transactional、@Cacheable、@Async等),在使用不当时,很可能会失效。失效的情况有很多种,本文我们就来瞅瞅,为啥同一个类中普通方法调用Spring注解方法,注解会失效呢?

有一些同学可能不知道其中原由,别急,让我来为大家揭晓答案。

v2-101571ab9b720d65bb60bbce1fb99a0c_b.jpg
听说你很懂源码?Spring读懂了?还有这20道源码面试题接得住吗?​zhuanlan.zhihu.com
v2-61b8937e1f7ae1b8668da2c85e23f38d_120x160.jpg

Spring在扫描bean的时候,如果扫描到方法上有这些注解,那么spring会通过动态代理模式,为这个bean动态地生成一个代理类,在代理类中,会对有注解的这个方法,做一些增强处理,如给有@Transactional注解的方法开启transaction。

当我们想要调用这个方法时,实际上是先调用了代理对象中被增强的方法,然后在代理对象中,又会调用我们实际的目标对象中的方法。在通过代理对象中转的这一过程中,像上边说的开启和提交transaction就实现了。

实现机制我们大体知道了,下面我们用代码来模拟演示一下。

假设我们订单业务处理类中,有两个方法:校验订单参数方法verifyOrderParameters() 和 保存订单方法saveOrder(),其中saveOrder方法上加了@Transactional注解,verifyOrderParameters方法内会调用saveOrder方法。

OrderService

/**
 * 订单业务层的接口定义
 */
public interface OrderService {

    /**
     * 校验订单参数
     */
    void verifyOrderParameters();

    /**
     * 保存订单
     */
    void saveOrder();
}

OrderServiceImpl

/**
 * 订单业务层的具体处理类
 */
public class OrderServiceImpl implements OrderService{

    @Override
    public void verifyOrderParameters() {
        System.out.println("校验订单参数");
        // 调用保存订单方法
        saveOrder();
    }

    @Override
    @Transactional
    public void saveOrder() {
        System.out.println("保存订单信息到DB");
    }
}

我们用伪代码来演示一下Spring动态代理生成的代理类。

OrderServiceImplProxy

/**
 * 订单业务层具体处理类的代理类
 */
public class OrderServiceImplProxy implements OrderService{

    /**
     * 持有被代理的具体的目标对象
     */
    private OrderServiceImpl orderServiceImpl;

    public OrderServiceImplProxy(OrderServiceImpl orderServiceImpl) {
        this.orderServiceImpl = orderServiceImpl;
    }

    @Override
    public void verifyOrderParameters() {
        orderServiceImpl.verifyOrderParameters();
    }

    @Override
    public void saveOrder() {
        System.out.println("开启事务。。。");
        orderServiceImpl.saveOrder();
        System.out.println("提交事务。。。");
    }
}

边我们来看下客户端调用saveOrder方法和verifyOrderParameters方法,输出结果都是什么样的。

public class Client {

    public static void main(String[] args) {
        // 创建一个订单业务的真实处理对象
        OrderServiceImpl orderServiceImpl = new OrderServiceImpl();
        // 创建一个代理对象
        OrderServiceImplProxy orderServiceImplProxy = new OrderServiceImplProxy(orderServiceImpl);
        // 执行代理对象的校验订单方法
        orderServiceImplProxy.verifyOrderParameters();
        System.out.println("--------------------------------------------");
        // 执行代理对象的保存订单方法
        orderServiceImplProxy.saveOrder();
    }
}

执行main方法后,得到下边的输出:

校验订单参数
保存订单信息到DB
--------------------------------------------
开启事务。。。
保存订单信息到DB
提交事务。。。

通过这个演示代码,想必同学们已经了解了吧,普通方法verifyOrderParameters内调用注解方法saveOrder时,其实调用的是原目标对象(orderServiceImpl)的saveOrder方法,没有走代理对象(orderServiceImplProxy)中被增强的saveOrder方法,所以就不会产生效果啦。

动态代理是实现Spring AOP的一个重要手段,所以大家以后再用注解以及切面时,一定要注意这个坑噢。

作者:晓呆同学
原文链接: https:// blog.csdn.net/daidainet easy/article/details/105981724
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值