Spring框架、02SpringAOP

SpringAOP

日志功能

基本方法

分析代码问题

  • 目前代码存在两个问题

    1. 代码耦合性高:业务代码和日志代码耦合在了一起

    2. 代码复用性低:日志代码在每个方法都要书写一遍

    b31e43aadec943448080c05dedd2b553.png
  • 问题解决方案

    1. 使用动态代理,将公共代码抽取出来

    630a1dfc7afe4e11abfd70e7007fd1ca.pnge69f0c222e314394b0f06d4bd032168d.png

JDK动态代理

使用JDK动态代理创建代理对象,完成日志的记录步骤分析

  1. 导入初始工程

  2. 确定目标类(被代理的类)

  3. 确定增强类(要给被代理类添加的功能)

  4. 使用JDK技术创建代理对象,然后调用其方法

    d51a4bd80d3c47a2a081349d60794212.png

动态代理: 目标对象(EmpServiceImpl) + 增强逻辑(Logger) = 代理对象

360b02a65930457d9c1a4e256606717e.png

基于JDK动态代理产生的代理对象与被代理对象是兄弟关系,二者实现同一个接口

CGLIB动态代理

动态代理: 目标对象(EmpServiceImpl) + 增强逻辑(Logger) = 代理对象

774dbf71caed43de8ac731464d96113c.png

基于Cglib动态代理产生的代理对象与被代理对象是父子关系,代理对象是被被代理对象的儿子

JDK和CGLIB

  • 首先明确在创建代理对象时,jdk的速度要高于cglib 所以选择的时候:

    1. 当被代理类有接口的时候,使用jdk动态代理

    2. 当被代理类没有接口的时候,使用cglib动态代理

AOP

AOP介绍

AOP介绍

  • AOP(Aspect Oriented Programming)面向切面编程

    1. 编码过程中将各个辅助功能分开编写, 运行时再将其织入到核心代码中

    2. 这种思想的实现技术是:动态代理(jdk、cglib)

    8a84f7b5959c46c1bb8c293318f687c3.png
  • SpringAOP就是为了简化动态切入这部分操作,开发者只需要通过少量的声明式配置,就可以实现AOP的编程 Spring会根据被代理的类是否有接口自动选择代理方式:

    1. 如果有接口,就采用jdk动态代理

    2. 如果没接口,就采用cglib的方式

    ececb4e52388460b8670974363ea2ac8.png

AOP术语

  1. 目标对象(Target) 被代理的对象

  2. 连接点(JoinPoint) 目标对象中得所有方法

  3. 切入点(PointCut) 目标对象中得要进行功能增强那部分方法

  4. 增强 (Advice 通知) 一个具体增强功能(增强对象 增强方法)

  5. 切面 (Aspect) 切面是一种描述,描述的是: 增强方法和切点方法的执行顺序(哪个增强方法在哪个切点的什么位置执行)

快速入门

使用SpringAop完成在业务层类中的方法上打印日志

基础步骤

  1. 创建模块,导入依赖

  2. 创建实体类

  3. 创建业务层接口和实现类

  4. 创建日志类

  5. 创建配置类

  6. 测试

动态代理步骤

  1. 在增强类中配置切点和切面

  2. 在配置类中激活切面代理

  3. 测试

在案例中体现的优势

  • 场景

    48c524fe9d394afe942ff47a73add471.png
  • 优势

    dd5d6464487641e18d12bca8a33efeec.png

通知类型

通知类型

  1. @Before:前置通知,此注解标注的通知方法在目标方法前被执行

  2. @AfterReturning: 返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行

  3. @AfterThrowing: 异常后通知,此注解标注的通知方法发生异常后执行

  4. @After:后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行

注意事项

  • @Around环绕通知需要自己调用 ProceedingJoinPoint.proceed() 来让原始方法执行,其他通知不需要考虑目标方法执行

  • @Around环绕通知方法的返回值,必须指定为Object,来接收原始方法的返回结果

通知顺序

  • 当有多个切面的切入点都匹配到了目标方法,目标方法运行时,多个通知方法都会被执行。

  • 执行顺序

    1. 不同切面类中,默认按照切面类的类名字母排序:

      • 目标方法前的通知方法:字母排名靠前的先执行

      • 目标方法后的通知方法:字母排名靠前的后执行

      b63140cc32d74de88ac90c73a4746409.png
    2. 用 @Order(数字) 加在切面类上来控制顺序

      • 目标方法前的通知方法:数字小的先执行

      • 目标方法后的通知方法:数字小的后执行

    c3b27e1e72ca46329be5f779584a4031.png

切点表达式

@PointCut

切点表达式

  • 切入点表达式:描述切入点方法的一种表达式

  • 作用:主要用来决定项目中的哪些方法需要加入通知

  • 常见形式:

    1. execution(……):根据方法的签名来匹配

    2. @annotation(……) :根据注解匹配

    c68e5a153d53460189410d80da7aedf6.png

切入点表达式-execution

e4a9435cc6ed4de7b5466eb8ebd424f2.png

execution 主要根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配,语法为:

85533bf2dda94ab49dfa6c673fb1ec3c.png

  • 其中带 ? 的表示可以省略的部分

  • 表达式中支持使用一些特殊符号进行模糊匹配

    1. * 用于匹配1个位置

    2. .. 用于匹配0个或1个或多个位置,简单说就是任意位置

切入点表达式-@annotation

e31663e035cc49b19176cbe43014c8ca.png

@annotation 用于匹配标识有特定注解的方法

749da9de7aa54038910938021e655bcd.png

事务管理

事务回顾

事务回顾

  1. 概念

  • 事务 是一组操作的集合,它是一个不可分割的工作单元,这些操作 要么同时成功,要么同时失败。

  1. 操作

  • 开启事务(一组操作开始前,开启事务):start transaction / begin ;

  • 提交事务(这组操作全部成功后,提交事务):commit ;

  • 回滚事务(中间任何一个操作出现异常,回滚事务):rollback ;

事务管理

Spring事务管理

注解

  • 注解:@Transactional 位置:业务(service)层的方法上、类上、接口上

  • 作用:将当前方法交给spring进行事务管理,方法执行前,开启事务;成功执行完毕,提交事务;出现异常,回滚事务

c113696e61194ea8a2184aee25695176.png

事务属性

事务属性-回滚

rollbackFor

  • 默认情况下,只有出现 RuntimeException 才回滚异常,rollbackFor属性用于控制让非运行时异常也回滚。

7b1cca950fe5475b819fc6e0eddacd01.png

事务属性-传播行为

propagation

  • 事务传播行为:指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制。

1ac1862af4c8457f88ac706766a767b0.png

属性值 含义
REQUIRED 【默认值】需要事务,有则加入,无则创建新事务
REQUIRES_NEW 需要新事务,无论有无,总是创建新事务
SUPPORTS 支持事务,有则加入,无则在无事务状态中运行
NOT_SUPPORTED 不支持事务,在无事务状态下运行,如果当前存在已有事务,则挂起当前事务
MANDATORY 必须有事务,否则抛异常
NEVER 必须没事务,否则抛异常
 

场景

  • REQUIRED :大部分情况下都是用该传播行为即可。

  • REQUIRES_NEW :当我们不希望事务之间相互影响时,可以使用该传播行为。 比如:下订单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功

 

相关推荐

  1. 后端主流框架--Spring02

    2024-07-19 22:44:03       24 阅读
  2. SpringSpringAop给所有Service增加日志

    2024-07-19 22:44:03       58 阅读
  3. Spring框架

    2024-07-19 22:44:03       22 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 22:44:03       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 22:44:03       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 22:44:03       45 阅读
  4. Python语言-面向对象

    2024-07-19 22:44:03       55 阅读

热门阅读

  1. 本地搭建ros2环境步骤(x86_64架构)

    2024-07-19 22:44:03       17 阅读
  2. vue实现可拖拽dialog封装

    2024-07-19 22:44:03       19 阅读
  3. 网络安全-网络安全及其防护措施4

    2024-07-19 22:44:03       18 阅读
  4. php cms 如何适配php8.3

    2024-07-19 22:44:03       13 阅读
  5. 聚类优化:Scikit-Learn中的数据标签分配艺术

    2024-07-19 22:44:03       16 阅读
  6. 【乐吾乐2D可视化组态编辑器】切换画面

    2024-07-19 22:44:03       17 阅读
  7. 第4章 Express路由的深入理解(一)

    2024-07-19 22:44:03       16 阅读
  8. CSS实现从上往下过渡效果

    2024-07-19 22:44:03       16 阅读