spring 事务机制

在spring中实现事务可以有两种方式

一.编程式事务

最简单的是使用TransactionTemplate

有返回值的用TransactionCallback

无返回值的用TransactionCallbackWithoutResult

二.声明式事务 也就是加入@Transactional注解

Spring 的声明式事务本质上是通过AOP来增强的类的功能
Spring 的AOP本质上就是为类做了一个代理(看似在调用自己写的类,实际用的是增强后的代理类)
访问增强后的代理类,而非直接访问自身的方法

接下来看下面的场景

假如有个接口,它包含两个方法a和b,然后有一个类实现了该接口。在该实现类里在a上标上事务注解、b上不标,此时事务是怎样的?

//接口
interface Service {
    void a();

    void b();
}

//目标类,实现接口
class ServiceImpl implements Service {

    @Override
    //如果抛 RollbackException就回滚
    @Transactional(rollbackFor = RollbackException.class)
    public void a() throws RollbackException {
        jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('BBB')");
        throw new RollbackException();
    }

    @Override
    public void b() throws RollbackException {
        a();
    }
}

答案是a方法不会被事务回滚。


因为 @Transactional其实是为你的类做了一个代理,既然是代理类那么只有调用代理类才能真正的
执行到增强的方法,如果是在类的内部调用的化意味着没有调用增强的方法,因此b调用了一个
被@Transactional 注解的方法a但是本身b没有被事务增强所以a也不会有事务的支持。

用代码表示大概如下

//代理类,也要实现相同的接口
class ProxyByJdkDynamic implements Service {

    //包含目标对象
    private Service target;

    public ProxyByJdkDynamic(Service target) {
        this.target = target;
    }

    //目标类中此方法带注解,进行特殊处理
    @Override
    public void a() {
       
        System.out.println("开启事务");
        //调用目标对象的方法,该方法已在事务中了
        target.a();
        System.out.println("提交事务");
    }

    //目标类中此方法没有注解,只做简单的调用
    @Override
    public void b() {
        //直接调用目标对象方法
        target.b();
    }
}

那么如果既想通过b调用a还想a被事务管理应该怎么做?

方法有三种

1.在b方法加入@Transactional注解

2.将接口类注入进来通过接口类来调用a方法

 @Autowired
 private Service service;
 ..
 @Override
 public void b() throws RollbackException{
   service.a();
 }

3. 在当前类的方法中通过AopContext.currentProxy()获取当前类的代理对象,再调用的代理对象的方法(其实是增强后的方法)

 //获取当前代理,这样写避免了自己调用自己的实例
  @Override
  public void b() throws RollbackException {
      ((Service) (AopContext.currentProxy())).a();
  }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值