当前位置: 首页 > news >正文

百合居装饰公司北京网站优化怎么样

百合居装饰公司,北京网站优化怎么样,wordpress二维码制作教程,晋城有做网站的吗SpringBoot中事务失效的原因 文章目录 SpringBoot中事务失效的原因一、事务方法非public修饰二、非事务方法调用事务方法三、事务方法的异常被捕获四、事务异常类型不对五、事务传播行为不对六、没有被Spring管理6.1、暴漏代理对象6.2、使用代理对象 常见的事务失效原因包括如下…

SpringBoot中事务失效的原因

文章目录

  • SpringBoot中事务失效的原因
    • 一、事务方法非public修饰
    • 二、非事务方法调用事务方法
    • 三、事务方法的异常被捕获
    • 四、事务异常类型不对
    • 五、事务传播行为不对
    • 六、没有被Spring管理
      • 6.1、暴漏代理对象
      • 6.2、使用代理对象

常见的事务失效原因包括如下六个

一、事务方法非public修饰

由于Spring的事务是基于AOP的方式结合动态代理来实现的。因此事务方法一定要是public的,这样才能便于被Spring做事务的代理和增强。

而且,在Spring内部也会有一个 org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource类,去检查事务方法的修饰符:

	protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {// Don't allow no-public methods as required.if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null;}// 省略}

二、非事务方法调用事务方法

@Service
public class OrderService {    public void createOrder(){// ... 准备订单数据// 生成订单并扣减库存insertOrderAndReduceStock();}    @Transactionalpublic void insertOrderAndReduceStock(){// 生成订单insertOrder();// 扣减库存reduceStock();}   
}

可以看到,insertOrderAndReduceStock方法是一个事务方法,肯定会被Spring事务管理。Spring会给OrderService类生成一个动态代理对象,对insertOrderAndReduceStock方法做增加,实现事务效果。

但是现在createOrder方法是一个非事务方法,在其中调用了insertOrderAndReduceStock方法,这个调用其实隐含了一个this.的前缀。也就是说,这里相当于是直接调用原始的OrderService中的普通方法,而非被Spring代理对象的代理方法。那事务肯定就失效了!

三、事务方法的异常被捕获

异常被捕获了但是没有往外抛异常,所以事务没有发现方法中出现错误,所以也就没有回滚

在这段代码中,reduceStock方法内部直接捕获了Exception类型的异常,也就是说方法执行过程中即便出现了异常也不会向外抛出。

而Spring的事务管理就是要感知业务方法的异常,当捕获到异常后才会回滚事务。

现在事务被捕获,就会导致Spring无法感知事务异常,自然不会回滚,事务就失效了。

四、事务异常类型不对

@Transactional(rollbackFor = RuntimeException.class)
public void createOrder() throws IOException {// ... // 准备订单数据// 生成订单insertOrder();// 扣减库存reduceStock();throw new IOException();
}

在这里插入图片描述

Spring的事务管理默认感知的异常类型是RuntimeException,当事务方法内部抛出了一个IOException时,不会被Spring捕获,因此就不会触发事务回滚,事务就失效了。

因此,当我们的业务中会抛出RuntimeException以外的异常时,应该通过@Transactional注解中的rollbackFor属性来指定异常类型:

@Transactional(rollbackFor = Exception.class)

五、事务传播行为不对

@Transactional
public void createOrder(){// 生成订单insertOrder();// 扣减库存reduceStock();throw new RuntimeException("业务异常");
}
@Transactional  // 默认的是如果当前没有事务,自己创建事务,如果有事务则加入
public void insertOrder() {}
// 不管当前方法所在方法有没有都开启一个事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void reduceStock() {}

在示例代码中,事务的入口是createOrder()方法,会开启一个事务,可以成为外部事务。在createOrder()方法内部又调用了insertOrder()方法和reduceStock()方法。这两个都是事务方法。

不过,reduceStock()方法的事务传播行为是REQUIRES_NEW,这会导致在进入reduceStock()方法时会创建一个新的事务,可以成为子事务。insertOrder()则是默认,因此会与createOrder()合并事务。

因此,当createOrder方法最后抛出异常时,只会导致insertOrder方法回滚,而不会导致reduceStock方法回滚,因为reduceStock是一个独立事务。

所以,一定要慎用传播行为,注意外部事务与内部事务之间的关系。

六、没有被Spring管理

即当前类没有被SpringBoot扫描

第二种事务失效的解决方案:

上面的问题在于非事务方法中调用事务方法其中隐含了一个this.的前缀, 虽然当前方法的事务也被代理类生成了,但是因为默认关键字的原因,调用的还是原来的是没有事务的方法.

所以我们现在要做的就是要找到被代理之后的类,然后再在方法中调用该方法

6.1、暴漏代理对象

在启动类上添加注解,暴露代理对象:

@EnableAspectJAutoProxy(exposeProxy = true)

6.2、使用代理对象

通过AopContext拿到当前类的代理对象,然后调用对应方法

IUserCouponService userCouponService = (IUserCouponService) AopContext.currentProxy();
userCouponService.insertCouponAndCheck(userId, coupon, null);

注意:何时会产生代理对象?只有代理对象在调用方法的时候才会将当前代理对象暴漏在当前线程中

http://www.hengruixuexiao.com/news/20395.html

相关文章:

  • 公安 网站 源码深圳百度推广开户
  • 工厂订单外发代加工外发加工网在线网站seo诊断
  • 一流的内蒙古网站建设网络广告营销方案策划
  • 南昌网站优化公司优化大师怎么提交作业
  • 群晖远程管理wordpress优质的seo快速排名优化
  • 南昌做公司网站哪家好免费seo网站自动推广
  • wordpress 极简企业网站优化价格
  • 如何看出网站用dede做的百度热搜榜排名今日头条
  • 做胃镜多少钱天津津门网站I宁波seo排名外包公司
  • 网站怎么做留言板块免费涨热度软件
  • 企业网站建设方案.doc广东清远今天疫情实时动态防控
  • 如何创办一个赚钱的网站seo工作怎么样
  • 网站建设boss都知道抓取关键词的软件
  • 南通网站推广排名北京网站制作推广
  • 恩施建设厅网站怎么用网络推广业务
  • 公司建设网站需要什么条件seo搜索引擎优化关键词
  • 商务网站建设与维护试题seo最新优化技术
  • 出国留学网站开发关键词自动优化工具
  • 做动图为所欲为的网站引擎seo优
  • 中企动力做网站行吗宁波怎么优化seo关键词
  • 送菜网站制作武汉网络推广公司排名
  • php网站 数据库链接杭州做搜索引擎网站的公司
  • 个人做的网站有什么危险吗网站搜索引擎优化的基本内容
  • 网站建设项目需求概要说明书以网络营销为主题的论文
  • 多钱网网站上海优化seo排名
  • 网站建设学习手机百度提交入口
  • 珠海市网站建设公司怎么建立一个属于自己的网站
  • 南京 网站开发简述网站推广的意义和方法
  • 做论坛网站需要多少钱seo点击软件哪个好用
  • 在哪些网站可以做企业名称预审网络广告策划案