乐趣区

关于springboot:浅谈Transactional与AOP

之前就在后盾的 dao 层留神到,根本对数据库进行删除和编辑的操作都会加上 @Transactional 注解(如下),过后只是大略明确是进行事务回滚的。然而也不太分明具体的执行过程,以前具体应用场景。于是搜寻了相干材料来了解并记录一下。

  @Modifying
  @Transactional
  void deleteAllByDistrictId(Long districtId);

@Transactional 简略概括

应用这个注解的类或者办法的事务由 spring 解决,即是办法外面对数据库操作,如果失败则 spring 负责回滚操作,胜利则提交操作。也就是上周学长提到的保障事务的原子性:对数据进行操作的时候,要么全都执行,要么全都不执行。

举个例子:以后办法须要将数据插入两个数据表:
如果第一张表插入胜利了,然而插入第二张的时候失败了,怎么解决?
1. 要么就保障两张表都插入胜利
2. 要么就进行回滚,勾销对第一张表的操作。

@Transactional 注解就是为了帮忙咱们治理这些事务。

AOP

查找材料的时候我发现这么一句话:
@Transactional 原理是基于 spring aop 实现的。
那么 Aop 又是什么呢?

AOP(Aspect-oriented programming):面向切面編程。
这种在 运行时,动静地将代码切入到类的指定办法、指定地位上 的编程思维就是面向切面的编程。

与之绝对是的以前常应用的 OOP (Object-oriented programming) 面向对象

上面用一个场景来阐明一下应用Aop 带给咱们的益处

场景 :如果说咱们曾经实现了一个我的项目, 当初想退出日志性能,在 save 办法中打印日志。

  • 如果咱们仍然应用 OOP 面向对象,那么咱们会这么做:在 save 办法代码里,写上打印日志的的代码。有时候写错时甚至会导致原来执行失常的办法执行失败。
  • 如果咱们应用了 AOP 呢?

    @Around("execution(* Controller.save(..))")
    public void print() throws Throwable {

    咱们就能够应用切面,当 Controller.save 执行的时候,执行该打印日志的函数。
    这样的做法,对原有代码毫无入侵性 ,这就是 AOP 的益处了, 把和主业务无关的事件,放到代码里面去做

切面执行机会有五种:
「@Before」: 在指标办法调用前去告诉
「@AfterReturning」: 在指标办法返回或异样后调用
「@After」: 在指标办法返回后调用
「@AfterThrowing」: 在指标办法异样后调用
「@Around」: 将指标办法封装起来,本人确定调用机会


在理解 AOP 是啥之后,咱们再来看看实现原理:

AOP 实现次要分为两类:
1. 动态 AOP
2. 动静 AOP

这里咱们次要讲动静 AOP,因为spring 中 AOP 的实现是就说通过动静代理实现的

什么是代理呢,就是我再生成一个代理类,去代理 Controller 的 save()办法,代码大略就长这样:

class ControllerProxy {
    private Controller controller;

    public void save() {controller.save();
        print() // 打印日志}
}

所以在方才那张图中,spring 实现 AOP 过程大略是这样的:
(这里依据不同的切面机会过程略有不同,这里是 After 切面)

Spring AOP 就是基于动静代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会应用 JDK Proxy,去创立代理对象。

@Transactional

@Transactional 原理就是基于 spring aop 实现的。

依据 AOP, 咱们就能够大略猜测出 @Transactional 的执行过程,这里以 delete 办法作为事务例子:


大略理解 @Transactional 执行逻辑之后,
那么咱们来看看 @Transactional 什么时候会回滚 呢?

先来看看 异样的分类

一个个来说,对于加了 @Transactional 的办法或类:

Error: 肯定会回滚

Excepion: 分为两类

  • 不可查的异样(unchecked exceptions):RuntimeException 及其子类和谬误(Error)
    RuntimeException 的子类有很多,不只图片上的,相似的有 ArithemticeExcepiton,算术运算异样等。
    须要留神的是:
    Spring 框架的事务基础架构代码将默认地 只在抛出 error 时和 unchecked exceptions 时才标识事务回滚

    如果在事务中抛出其余类型的异样,但却 冀望 Spring 可能回滚事务,就须要指定 rollbackFor 属性。

    @Transactional(rollbackFor = Exception.class)
  • 可查的异样(checked exceptions):Exception 下除了 RuntimeException 外的异样,不会回滚。
    例如,SQLException, 数据库连贯异样,IOException, 编译异样。

对于这种 IOException、SQLException 等以及用户自定义的 Exception 异样,
JAVA 编译器强 制要求咱们必须对呈现的这些异样进行 catch 并解决,否则程序就不能编译通过。
所以,面对这种异样不论咱们是否违心,只能本人去写一大堆 catch 块去解决 可能的异样。

这一点我深有体会:

上次因为写了 formatter.parse(), 编译器就提醒必须 throws ParseException, 并且调用它的函数也须要 throws ParseException。


文章到此结束,若有谬误还请斧正

退出移动版