浅谈 Spring AOP 思想

Spring AOP

  • AOP 切面编程
    • 普通代理类
    • JDK动态代理
    • Cglib动态代理
    • AOP
      • AOP术语
      • AOP切面编程的优势
      • Advice通知类型(5种)
      • 通知的执行顺序 @Order
      • 切入点表达式
        • 表达式@execution
        • 注解@annotation
  • Spring事务管理
    • @Transactional 及 @Transactional 的两个属性
      • @Transactional 的 rollback 回滚 属性
      • @Transactional 的 propagation 传播行为 属性
  • AOP相关注解总结(十一)
    • 配置切面相关注解
    • 通知相关注解
    • 事务相关注解

AOP 切面编程

AOP 底层是基于动态代理思想实现的 可以把核心业务业务逻辑看作是一个圆增强的业务逻辑也看成是一个圆,核心业务逻辑在增强的业务逻辑的中央,这样就形成了一个同心圆(切面), 这种编程思想的好处是 无侵入 即 不会对源码进行修改。以一个为核心业务逻辑增加日志的例子来逐步引出动态代理和AOP面向切面编程思想。

普通代理类

最原始的方式是利用代理类的方式为核心业务逻辑增添打印日志的功能,这就要求被代理类和增强类要同时实现一个接口来保证方法的一致性,但是还需要为每一个代理类都创建一个对象,当增强的方法都相同时就造成了代码的重复编写,造成了开发效率的降低。下面这种是修改源码的方式。
在这里插入图片描述
在这里插入图片描述

目前代码存在两个问题
代码耦合性高:业务代码和日志代码耦合在了一起
代码复用性低:日志代码在每个方法都要书写一遍

在这里插入图片描述

JDK动态代理

为了解决基本代理方式的不足,产生了JDK动态代理的方式,但是这样的方式还有一个不足,就是只能对接口的实现类进行代理,在此背景下,Cglib动态代理又出现了,Cglib动态代理可以为类动态创建代理类。
PS: 在创建代理对象时 jdk的速度要高于cglib
所以选择的时候:
当被代理类有接口的时候,使用jdk动态代理
当被代理类没有接口的时候,使用cglib动态代理

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class DeptServiceTest {@Autowiredprivate DeptService deptService;@Autowiredprivate Logger logger;@Testpublic void test1() {InvocationHandler myHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {logger.m1();try {method.invoke(deptService,args);} catch (Exception e) {logger.m3();}logger.m2();return null;}};DeptService deptServiceproxy = (DeptService) Proxy.newProxyInstance(deptService.getClass().getClassLoader(),new Class[]{DeptService.class},myHandler);deptServiceproxy.save(null);deptServiceproxy.findAll();deptServiceproxy.findById(null);}}

在这里插入图片描述

Cglib动态代理

在这里插入图片描述

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class DeptServiceTest {@Autowiredprivate DeptServiceImpl deptService;@Autowiredprivate Logger logger;@Testpublic void test01() {InvocationHandler invocationHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {logger.m1();try {method.invoke(deptService, args);} catch (Exception e) {logger.m3();}logger.m2();return null;}};DeptServiceImpl deptServiceProxy = (DeptServiceImpl) Enhancer.create(DeptServiceImpl.class, invocationHandler);//注意: Enhancer有个硬伤,就是无法对已经封装过的targetclass,再继续封装多一次,无法实现多个interceptor的链式调用。deptServiceProxy.findAll();System.out.println("=============================");deptServiceProxy.save(null);System.out.println("=============================");deptServiceProxy.findById(null);}
}

首先通过enhancer创建代理类,再创建代理类的实例对象
在这里插入图片描述

AOP

切面类要使用两个注解 @Component 和 @Aspect 声明该类为一个切面类,并且将该切面类加入到Spring容器中,在切面类中可以定义切点 @ PointCut()和通知 (5种),下面会展开详细叙述
在这里插入图片描述

AOP术语

在这里插入图片描述

AOP切面编程的优势

在这里插入图片描述

Advice通知类型(5种)

@Before:前置通知,此注解标注的通知方法在目标方法前被执行
@AfterReturning: 返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
@AfterThrowing: 异常后通知,此注解标注的通知方法发生异常后执行
@After:后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行

@Around

@Around环绕通知需要自己调用 ProceedingJoinPoint.proceed() 来让原始方法执行,其他通知不需要考虑目标方法执行
@Around环绕通知方法的返回值,必须指定为Object,来接收原始方法的返回结果  Object result = pjp.proceed();

通知的执行顺序 @Order

不同切面类中,默认按照切面类的全类名字母排序:
目标方法前的通知方法:字母排名靠前的先执行
目标方法后的通知方法:字母排名靠前的后执行
相当于一个嵌套的效果一样,类比Filter中的过滤器链的执行顺序,也是按照全类名字母靠前的先执行

切入点表达式

切入点表达式:描述切入点方法@PointCut()的一种表达式
作用:主要用来决定项目中的哪些方法需要加入通知
常见形式:
在这里插入图片描述

表达式@execution

execution(……):根据方法的签名来匹配,常与通配符(* 和 …)搭配使用 ,…用在参数表示0或n个参数 *模糊匹配

使用切入点表达式 需要指定 权限修饰符 返回值类型 方法名的全名(带全类名) 参数 ,因此excution常与通配符搭配用来定义方法名有规律的切入点
在这里插入图片描述

注解@annotation

@annotation(……) :根据注解匹配,使用注解方式,需要自定义注解,常用来定义方法名无规律的切入点pointcut,自定义注解,如下所示:@annotation(注解全类名)

在这里插入图片描述

在切点配置自定义注解,用于识别对那些方法进行增强
在这里插入图片描述
配置切点注解
在这里插入图片描述

Spring事务管理

在Spring容器中使用事务时还需要在Spring配置类中配置@EnableTransactionMangement注解和@Bean配置事务管理器
在这里插入图片描述

@Transactional 及 @Transactional 的两个属性

位置:业务(service)层的方法上、类上、接口上
作用:将当前方法交给spring进行事务管理,方法执行前,开启事务;成功执行完毕,提交事务;出现异常,回滚事务

注解用在方法上,表示为方法开启事务,用在类上表示为类中所有方法开启事务,用在接口上表示为接口的所有实现类开启事务

@Transactional 的 rollback 回滚 属性

默认情况下,只有出现 RuntimeException 才回滚异常,rollbackFor属性用于控制让非运行时异常也回滚。
因此,需要为 @Transactional的rollback属性指定异常类类型让其对所有异常都进行回滚
在这里插入图片描述

@Transactional 的 propagation 传播行为 属性

事务传播行为:指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制。通俗点说就是:一个有事务注解修饰的方法在被另一个开启了事务的方法调用时,该方法的事务怎么办的问题。默认值是required

在这里插入图片描述
2中比较常用的是 required (默认) 有事务就加入,无事务就创建新的 和 requires_new 事务不影响
在这里插入图片描述

AOP相关注解总结(十一)

配置切面相关注解

@Component

@Aspect

@PointCut

@annotation

通知相关注解

@Before
@AfterReturning
@AfterThrowing
@After
@Around
@Oredr

事务相关注解

@EnableTransactionMangement

@Transactional

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/13458.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常用直线模组的类型

目前,直线模组的应用非常广泛,而且直线模组的种类也有很多可以满足每个行业的应用要求,那么常见的直线模组类型有哪些,大家知道吗? 1、全封闭滚珠丝杆直线模组: 在半封闭式的基础上增加了不锈钢带防尘结构…

[Angular] Import TranslateModule in Angular 16

1.Background Angular 更新至V16版后,支援 standalone,故移除了 NgModule,而TranslateModule 又要在AppModule中 import,那该如何做呢? 2.NPM packages installation npm install ngx-translate/core npm install n…

BUUCTF——reverse3 适合新手的关于base64加密算法代码的分析

作为一个逆向小白,学了点加密算法就来BUU找点乐子,前7题蛮简单的,然后做到了reverse3,典型的base64加密算法,让我折腾了好久,写篇博客记录一下 顺便说下很多博客并没有对这里的加密算法进行代码上的分析&a…

分享VMware Workstation Pro ESXI7创建虚拟机和配置硬盘空间(分享自己的学习历程意在帮助有需要的小伙伴)

背景:因公司项目需求改用VMware Workstation Pro,已经使用1个月目前除了中途出现过一次问题被解决后一直稳定运行至今, 1:这里贴出拿出现的问题提示及解决方法的链接:解决vmWare ESXI 7.3报错; 2:如果你是第一次接触VMware Work…

Echarts 文字太长用省略号代替

xAxis: [{type: category,data: [materialUserEchartsDate.value[0] ? materialUserEchartsDate.value[0].name : ,materialUserEchartsDate.value[1] ? materialUserEchartsDate.value[1].name : ,materialUserEchartsDate.value[2] ? materialUserEchartsDate.value[2].na…

二、前端高德地图、渲染标记(Marker)引入自定义icon,手动设置zoom

要实现这个效果,我们先看一下目前的页面展示: 左边有一个图例,我们可以方法缩小地图,右边是动态的marker标记,到时候肯定时候是后端将对应的颜色标识、文字展示、坐标点给咱们返回、我们肯定可以拿到一个list&#xf…

【广州华锐互动】无人值守变电站AR虚拟测控平台

无人值守变电站AR虚拟测控平台是一种基于增强现实技术的电力设备巡检系统,它可以利用增强现实技术将虚拟信息叠加在真实场景中,帮助巡检人员更加高效地完成巡检任务。这种系统的出现,不仅提高了巡检效率和准确性,还降低了巡检成本…

企业级敏捷转型探索与实践︱极狐Gitlab战略运营部PMO郝韫

极狐Gitlab战略运营部PMO郝韫先生受邀为由PMO评论主办的2023第十二届中国PMO大会演讲嘉宾,演讲议题:企业级敏捷转型探索与实践。大会将于8月12-13日在北京举办,敬请关注! 议题简要: 打造持续创新、快速成长的敏捷组织…

python调用百度ai将图片/pdf识别为表格excel

python调用百度ai将图片识别为表格excel 表格文字识别(异步接口)图片转excel 表格文字识别V2图片/pdf转excel通用 表格文字识别(异步接口) 图片转excel 百度ai官方文档:https://ai.baidu.com/ai-doc/OCR/Ik3h7y238 使用的是表格文字识别(异步接口),同步…

【C#】微软的Roslyn 是个啥?

一、说明 Roslyn 是微软重写的C#编译器并开源。 Roslyn 是 C# 和 Visual Basic.NET 开源编译器的代号。以下是它如何在过去十年企业Microsoft的最黑暗中开始,并成为所有C#(和VB)的开源,跨平台,公共语言引擎&#xff0c…

springboot+mybatis-plus+vue+element+vant2实现短视频网站,模拟西瓜视频移动端

目录 一、前言 二、管理后台 1.登录 2.登录成功,进入欢迎页 ​编辑 3.视频分类管理 4. 视频标签管理 5.视频管理 6.评论管理 ​编辑 7.用户管理 8.字典管理 (类似于后端的枚举) 9.参数管理(富文本录入) 10.管…

Docker容器监控之 CAdvisor+InfluxDB+Granfana

通过docker stats命令可以很方便的看到当前宿主机上所有容器的CPU,内存以及网络流量等数据,一般小公司够用了。但是,docker stats统计结果只能是当前宿主机的全部容器,数据资料是实时的,没有地方存储、没有健康指标过线预警等功能…

VMware搭建Hadoop集群 for Windows(完整详细,实测可用)

目录 一、VMware 虚拟机安装 (1)虚拟机创建及配置 (2)创建工作文件夹 二、克隆虚拟机 三、配置虚拟机的网络 (1)虚拟网络配置 (2)配置虚拟机 主机名 (3&#xf…

(树) 剑指 Offer 26. 树的子结构 ——【Leetcode每日一题】

❓剑指 Offer 26. 树的子结构 难度:中等 输入两棵二叉树 A 和 B,判断 B 是不是 A 的子结构。(约定空树不是任意一个树的子结构) B 是 A 的子结构, 即 A 中有出现和B相同的结构和节点值。 例如: 给定的树 A: 3/ \4 5/ \1 2给定的树 B&…

stable-diffusion-webui汉化教程

第一种方法 1.打开stable diffusion webui,进入"Extensions"选项卡 2.点击"Install from URL" 3、注意"URL for extension’s git repository"下方的输入框 4、填入地址:https://github.com/VinsonLaro/stable-diffus…

C++多线程编程(包含c++20内容)

C多线程编程(包含c20内容) 文章目录 C多线程编程(包含c20内容)线程通过函数指针创建线程通过函数对象创建线程通过lambda创建线程通过成员函数创建线程线程本地存储取消线程自动join线程从线程获得结果 原子操作库原子操作原子智能指针原子引用使用原子类型等待原子变量 互斥互…

[JAVAee]文件操作-IO

本文章讲述了通过java对文件进行IO操作 IO:input/output,输入/输出. 建议配合文章末尾实例食用 目录 文件 文件的管理 文件的路径 文件的分类 文件系统的操作 File类的构造方法 File的常用方法 文件内容的读写 FileInputStream读取文件 构造方法 常用方法 Scan…

平均列顺序对列排斥能的影响

( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有3个节点,AB训练集各由5张二值化的图片组成,让A有6个1,B有4个1,并且让这10个1的位置没有重合。比较迭代次数的顺序。 其中有9组数据 差值结构 A-B 迭代次数 构造平均列 …

使用PyGWalker可视化分析表格型数据

大家好,可以想象一下在Jupyter Notebook中拥有大量数据,想要对其进行分析和可视化。PyGWalker就像一个神奇的工具,能让这项工作变得超级简单。它能获取用户的数据,并将其转化为一种特殊的表格,可以与之交互&#xff0c…

ES6 - promise.all和race方法的用法详解

文章目录 一、前言二、Promise.all()1,第一句:Promise.all()方法接受一个数组作为参数,且每一个都是 Promise 实例2,第二句:如果不是,就会先调Promise.resolve方法,将参数转为 Promise 实例再进…