首页 > 其他分享 >@Around(value =execution(* )) 的理解

@Around(value =execution(* )) 的理解

时间:2024-03-30 14:11:47浏览次数:29  
标签:逻辑 execution Around 业务 value 切点 注解 执行 方法

我们总是听到AOP ,又称面向切面编程,那面向切面编程在日常开发中的应用场景有哪些呢 ?

我们来一起梳理一下:

什么时候会用到面向切面编程呢 ?其实就是有一些公共的逻辑,需要在很多地方用到,那这些代码如果在每个位置都写一下的话,当需要修改的时候,又必须将这些代码全都找出来进行修改,就会很冗余,为了解决这个问题:将公共的代码抽取出来,当代码运行到指定位置的时候,将公共的代码逻辑切入到相应的位置,即使用AOP的方式进行编程。

使用的是代理机制,在不改变原程序的基础上对代码进行增强操作,比如:统一的日志记录、性能监控、异常处理、参数校验 等等这些非业务核心的功能,被单独抽取出来,与业务代码分离,横切在核心业务代码之上AOP就是在某一个类或者方法执行的某个时机,声明在执行到这里之前、之后、中途要执行什么,执行完之后要接着执行什么。

 

 

我们其实可以利用自定义注解 和 切面来实现同样的效果。

 

 

一、要使用AOP切面编程的话,需要明确几个问题:

1、通过什么方式切入,是通过自定义注解,还是说直接指定某些包的位置。

2、在何时进行切入,这就涉及到我们考虑在所做业务的什么时机进行切入,执行相应的切面方法。

3、切入之后,需要做的公用操作是什么 ?日志记录、参数校验、权限校验、一异常处理等等。

二、专业术语

接下来,我们一起来明确一些切面编程上的专业术语:其中

 

连接点(Joinpoint)、切点(Pointcut)、通知(Advice)、切面(Aspect)为主要部分。

  • 连接点Joinpoint 

连接点描述的是位置

在程序的整个执行业务流程中,可以织入切面的位置。比如在某些待切方法的执行前后、参数调用处,异常抛出之后等位置。这些位置都可以理解成连接点。

  • 切点Pointcut

切点本质上指方法,就是哪个方法将要被切入,那这个方法可以叫做切点(所以方法叫做切点,也就是执行过程中真正被植入切面的方法)

  • 通知 Advice

通知其实就是指要实现增强效果的那些代码方法。后面就知道了,比如加了@Before方法的test()方法,那这个方法就是通知。

注意:

切面(切点+通知)就是在一个正常竖向做的业务流程中 ,在某些时机做横向拦截,然后做一些处理, 通过切点切入。链接点的链接,最终SpringAOP会将其定义的内容织入到约定的流程中,在动态代理中可以把它理解成一个拦截器

 三、常见的通知类型:

  • 前置通知(before):在动态代理反射原有对象方法执行前   ,或者执行环绕通知前执行的通知功能。
  • 后置通知(after):在动态代理反射原有对象方法执行后 ,  或者执行环绕通知后执行的通知功能。无论是否抛出异常,他都会被执行。
  • 返回通知(afterReturning):在原有对象方法正常返回后,或者执行环绕通知后正常返回(无异常)执行的通知功能。
  • 异常通知(afterThrowing):在动原有对象方法异常返回后,或者执行环绕通知产生异常后执行的通知功能。
  • 环绕通知(around):他可以转向当前被拦截对象的方法,并让之继续执行。

四、通知的执行顺序

spring4.x版本的通知的执行结果顺序是:  https://blog.csdn.net/weixin_38174052/article/details/125281813

@Around注解方法的前半部分业务逻辑
->@Before注解方法的业务逻辑
->目标方法的业务逻辑
->@Around注解方法的后半部分业务逻辑(@Around注解方法内的业务逻辑若对ProceedingJoinPoint.proceed()方法没做捕获异常处理,直接向上抛出异常,则不会执行Around注解方法的后半部分业务逻辑;若做了异常捕获处理,则会执行)。
->@After(不管目标方法有无异常,都会执行@After注解方法的业务逻辑)这里是指被切入的方法的异常情况,而不是指切面方法是否发生异常的情况!!!这个的是亲自验证了一下。
->@AfterReturning(若目标方法无异常,执行@AfterReturning注解方法的业务逻辑)
->@AfterThrowing(若目标方法有异常,执行@AfterThrowing注解方法的业务逻辑)


 

spring源码版本是5.2.14

:所以包含通知注解的执行结果如下,
@Around注解方法的前半部分业务逻辑
->@Before注解方法的业务逻辑
->目标方法的业务逻辑
->@AfterThrowing(若目标方法有异常,执行@AfterThrowing注解方法的业务逻辑)
->@AfterReturning(若目标方法无异常,执行@AfterReturning注解方法的业务逻辑)
->@After(不管目标方法有无异常,都会执行@After注解方法的业务逻辑)
->@Around注解方法的后半部分业务逻辑(@Around注解方法内的业务逻辑若对ProceedingJoinPoint.proceed()方法没做捕获异常处理,直接向上抛出异常,则不会执行Around注解方法的后半部分业务逻辑;若做了异常捕获处理,则会执行)。

 如果还是感觉不太清晰,这些顺序的代码验证请看:  https://blog.csdn.net/monkey_wei/article/details/105521389

 要被增强的类及方法:

 正常执行结果如下:

 抛异常结果如下:

到此通知的执行顺序搞清楚啦 。

五、接下来我们在看看切点表达式,的具体规则:

 

1、切点表达式

切点表达式就是用来定义 通知 (Advice) 往哪些方法上 切入的。

  • 用于定义通知切入
  • 而且不局限于某个方法,可以切入多个方法
  • 告诉程序,这个切点可以匹配哪些方法

2、切点表达式的格式

execution([访问控制权限修饰符] 返回值类型 [全限定类名]方法名(形参)) [异常])

  •    访问权限修饰符:可选

  默认是4个权限都包括

  只写public就表示只包括公开的方法。

  • 返回值类型:必填

  星号* 表示返回值类型为任意

  • 全限定名:可选

  也就是类名,而且是具体的地址
  两个点 .. 代表当前包及其子包下所有的类
  省略时,表示所有的类

  • 方法名:必填

  星号* 表示所有方法
  比如 set* 表示所有的set方法

  • 形式参数列表: 必填

    • () ——表示没有参数的方法
    • (..) ——参数类型和个数随意的方法
    • (*) —— 只有一个参数的方法
    • (*,String) —— 第一个参数随意,第二个参数是String的
  • 异常:可选

    • 省略时表示任意类型的异常
理解以下切点表达式   :
@Around(value = "execution(* com.xxx.xxxs.*.controller..*(..))")   这个就代表是返回值是任意类型,的 com.xxx.xxxs.*.controller包下的所有类及子包下的所有类,中的所有方法,而且是任意数量参数的方法都会被切入。    

 

 

六、使用面向切面编程的可以解决的问题:

(1)前面提到了代理模式,可以极大的减少代码编写量,减少了代码耦合度,并且提高了可维护性

(2)对于复杂的业务,很多模块或者方法需要公用的逻辑:假设每个方法都需要日志/事务/权限,这些重复通用的业务和业务代码混杂在一起。交叉业务过多,就会导致以下两个问题

第一:交叉业务代码在多个业务流程中反复出现,显然这个交叉业务代码没有得到复用。并且修改这些交又业务代码的话,需要修改多处。(维护不便)
第二:程序员无法专注核心业务代码的编写,在编写核心业务代码的同时还需要处理这些交叉业务。

结合老杜的横向编程的图,更好理解

 

面向切面编程的优点

  1. 将于业务逻辑无关的通用业务逻辑代码单独提取出来,减少了对业务代码的干扰
  2. 便于维护
  3. 减少了代码编写量(冗余
  4. 遵循了OCP开闭原则,并且实现了解耦,降低了代码的耦合度
 

标签:逻辑,execution,Around,业务,value,切点,注解,执行,方法
From: https://www.cnblogs.com/isme-zjh/p/18097707

相关文章

  • Django中values()和values_list()
    values()1、不带参数,返回所有属性的键值对,比如使用filter时,会返回一个列表,列表中每一项是一个字典>>>Blog.objects.values()[{'id':1,'name':'BeatlesBlog','tagline':'AllthelatestBeatlesnews.'}],>>>Blog.objects.filte......
  • java.sql.BatchUpdateException: Date truncation: Out of range value for column xx
    报错:java.sql.BatchUpdateException:Datetruncation:Outofrangevalueforcolumnxxxxx原因:xxx列ddl中为stock_num(12,2)数据库值为0.06需要更新为:0.06-0.21就会出现该错误参考:https://www.jb51.net/article/158166.htmhttps://blog.csdn.net/stone_tomca......
  • 【基于价值分解网络的多智能体协同学习】【VDN】 【Value-Decomposition Networks For
    目录Value-DecompositionNetworksForCooperativeMulti-AgentLearning基于价值分解网络(VDN)的多智能体协同学习Abstract 摘要1Introduction引言1.1OtherRelatedWork 1.1其他相关工作2Background 2背景2.1ReinforcementLearning2.1强化学习​2.2De......
  • wpf write value to config file and read the persisted value
    <Windowx:Class="WpfApp26.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.......
  • 泛微e-cology_getE9DevelopAllNameValue2任意文件读取漏洞
    漏洞描述泛微e-cology依托全新的设计理念,全新的管理思想。为中大型组织创建全新的高效协同办公环境。智能语音办公,简化软件操作界面。身份认证、电子签名、电子签章、数据存证让合同全程数字化。泛微e-cologygetE9DevelopAllNameValue2接口存在任意文件读取漏洞,通过该漏洞......
  • AOP中的execution表达式
    文章目录前言一、知识讲解?1AOP是什么?2execution表达式二、使用execution表达式1.execution表达式2使用示例总结前言提示:这里可以添加本文要记录的大概内容:在学习Spring中,必然要学习AOP,那么execution表达式有是必不可少的。提示:以下是本篇文章正文内容,下面案......
  • 解决“AttributeError: ‘numpy.ndarray’ object has no attribute ‘value_counts’
    成功解决AttributeError:‘numpy.ndarray’objecthasnoattribute‘value_counts’大家好,今天我想分享一个我在Python编程过程中遇到的问题,并详细阐述我是如何解决的。这个问题是关于numpy.ndarray对象没有value_counts属性的AttributeError。一、问题背景与错误描述......
  • Key-N-Value--基于Protocol Buffers的树型协议处理引擎
    导言KNV是Key-Value协议的无限嵌套和模式自由的扩展,允许使用者快速访问或修改ProtoBuffers协议中的一部分或者多个部分,KNV原是一个面向对象缓存系统的一部分,后面作为腾讯第一批开源组件对外开源。KNV的理念也申请并获得国家专利。​​​​​​​项目地址:GitHub-shaneyuee/......
  • 面试官:只知道v-model是:modelValue和@onUpdate语法糖,那你可以走了
    前言我们每天都在用v-model,并且大家都知道在vue3中v-model是:modelValue和@update:modelValue的语法糖。那你知道v-model指令是如何变成组件上的modelValue属性和@update:modelValue事件呢?将v-model指令转换为modelValue属性和@update:modelValue事件这一过程是在编译时还是运行......
  • IfcSimpleValue
    IfcSimpleValue ChangelogItemSPFXMLChangeDescriptionIFC2x3toIFC4    IfcSimpleValue          IfcDateTime  ADDED       IfcDate  ADDED       IfcTime  ADDED       IfcDuration  ......