文章目录

  • 一、概述
  • 二、切点表达式配置
    • 1. 内置配置
    • 2. 注解配置
    • 3. 公共配置
  • 二、切点表达式类型
    • **`execution`**
    • **`within`**
    • **`this`**
    • **`target`**
    • **`args`**
    • **`bean`**
    • **`@within`**
    • **`@target`**
    • **`@annotation`**
    • **`@args`**
  • 三、切点表达式组合
  • 四、附录
    • 1. 常用注解
    • 2. 切点表达式类型
    • 3. 示例代码

Spring 的 AOP 中的一个核心概念是切点(Pointcut),切点表达式定义通知(Advice)执行的范围。

理解 AOP 通知参阅:《Spring AOP通知(Advice)详解》

一、概述

Spring AOP 只支持 Spring Bean 的方法切入,所以切点表达式只会匹配 Bean 类中的方法。

二、切点表达式配置

1. 内置配置

定义切面通知时,在 @Before@AfterReturning 等通知注解中指定表达式。

@Aspect
@Component
public class DemoAspect {@Before("execution(* cn.codeartist.spring.aop.advice.*.*(..))")public void doBefore() {// 自定义逻辑}
}

2. 注解配置

在切面类中,先定义一个方法并使用 @Pointcut 注解来指定表达式。
然后在定义切面通知时,在通知注解中指定定义表达式的方法签名。

@Aspect
@Component
public class DemoAspect {@Pointcut("execution(* cn.codeartist.spring.aop.aspectj.*.*(..))")private void pointcut() {// 切点表达式定义方法,方法修饰符可以是private或public}@Before("pointcut()")public void doBefore(JoinPoint joinPoint) {// 自定义逻辑}
}

3. 公共配置

在任意类中,定义一个公共方法并使用 @Pointcut 注解来指定表达式。

public class CommonPointcut {@Pointcut("execution(* cn.codeartist.aop.*..*(..))")public void pointcut() {// 注意定义切点的方法的访问权限为public}
}

在切面类中定义切面通知时,在通知注解中指定定义表达式的方法签名全路径。

@Aspect
@Component
public class DemoAspect {@Before("cn.codeartist.aop.CommonPointcut.pointcut()")public void commonPointcut() {// 自定义逻辑}
}

二、切点表达式类型

Spring AOP 支持以下几种切点表达式类型。

execution

匹配方法切入点。根据表达式描述匹配方法,是最通用的表达式类型,可以匹配方法、类、包。

表达式模式:

execution(modifier? ret-type declaring-type?name-pattern(param-pattern) throws-pattern?)

表达式解释:

  • modifier:匹配修饰符,public, private 等,省略时匹配任意修饰符

  • ret-type:匹配返回类型,使用 * 匹配任意类型

  • declaring-type:匹配目标类,省略时匹配任意类型

    • .. 匹配包及其子包的所有类
  • name-pattern:匹配方法名称,使用 * 表示通配符

    • * 匹配任意方法
    • set* 匹配名称以 set 开头的方法
  • param-pattern:匹配参数类型和数量

    • () 匹配没有参数的方法
    • (..) 匹配有任意数量参数的方法
    • (*) 匹配有一个任意类型参数的方法
    • (*,String) 匹配有两个参数的方法,并且第一个为任意类型,第二个为 String 类型
  • throws-pattern:匹配抛出异常类型,省略时匹配任意类型

使用示例:

// 匹配public方法
execution(public * *(..))// 匹配名称以set开头的方法
execution(* set*(..))// 匹配AccountService接口或类的方法
execution(* com.xyz.service.AccountService.*(..))// 匹配service包及其子包的类或接口
execution(* com.xyz.service..*(..))

within

匹配指定类型。匹配指定类的任意方法,不能匹配接口。

表达式模式:

within(declaring-type)

使用示例:

// 匹配service包的类
within(com.xyz.service.*)// 匹配service包及其子包的类
within(com.xyz.service..*)// 匹配AccountServiceImpl类
within(com.xyz.service.AccountServiceImpl)

this

匹配代理对象实例的类型,匹配在运行时对象的类型。

注意:基于 JDK 动态代理实现的 AOP,this 不能匹配接口的实现类,因为代理类和实现类并不是同一种类型,详情参阅《Spring中的AOP和动态代理》

表达式模式:

this(declaring-type)

使用示例:

// 匹配代理对象类型为service包下的类
this(com.xyz.service.*)// 匹配代理对象类型为service包及其子包下的类
this(com.xyz.service..*)// 匹配代理对象类型为AccountServiceImpl的类
this(com.xyz.service.AccountServiceImpl)

target

匹配目标对象实例的类型,匹配 AOP 被代理对象的类型。

表达式模式:

target(declaring-type)

使用示例:

// 匹配目标对象类型为service包下的类
target(com.xyz.service.*)// 匹配目标对象类型为service包及其子包下的类
target(com.xyz.service..*)// 匹配目标对象类型为AccountServiceImpl的类
target(com.xyz.service.AccountServiceImpl)

三种表达式匹配范围如下:

表达式匹配范围 within this target
接口
实现接口的类
不实现接口的类

args

匹配方法参数类型和数量,参数类型可以为指定类型及其子类。

使用 execution 表达式匹配参数时,不能匹配参数类型为子类的方法。

表达式模式:

args(param-pattern)

使用示例:

// 匹配参数只有一个且为Serializable类型(或实现Serializable接口的类)
args(java.io.Serializable)// 匹配参数个数至少有一个且为第一个为Example类型(或实现Example接口的类)
args(cn.codeartist.spring.aop.pointcut.Example,..)

bean

通过 bean 的 id 或名称匹配,支持 * 通配符。

表达式模式:

bean(bean-name)

使用示例:

// 匹配名称以Service结尾的bean
bean(*Service)// 匹配名称为demoServiceImpl的bean
bean(demoServiceImpl)

@within

匹配指定类型是否含有注解。当定义类时使用了注解,该类的方法会被匹配,但在接口上使用注解不匹配。

使用示例:

// 匹配使用了Demo注解的类
@within(cn.codeartist.spring.aop.pointcut.Demo)

@target

匹配目标对象实例的类型是否含有注解。当运行时对象实例的类型使用了注解,该类的方法会被匹配,在接口上使用注解不匹配。

使用示例:

// 匹配对象实例使用了Demo注解的类
@target(cn.codeartist.spring.aop.pointcut.Demo)

@annotation

匹配方法是否含有注解。当方法上使用了注解,该方法会被匹配,在接口方法上使用注解不匹配。

使用示例:

// 匹配使用了Demo注解的方法
@annotation(cn.codeartist.spring.aop.pointcut.Demo)

@args

匹配方法参数类型是否含有注解。当方法的参数类型上使用了注解,该方法会被匹配。

使用示例:

// 匹配参数只有一个且参数类使用了Demo注解
@args(cn.codeartist.spring.aop.pointcut.Demo)// 匹配参数个数至少有一个且为第一个参数类使用了Demo注解
@args(cn.codeartist.spring.aop.pointcut.Demo,..)

切点表达式的参数匹配

切点表达式中的参数类型,可以和通知方法的参数通过名称绑定,表达式中不需要写类或注解的全路径,而且能直接获取到切面拦截的参数或注解信息。

@Before("pointcut() && args(name,..)")
public void doBefore(String name) {// 切点表达式增加参数匹配,可以获取到name的信息
}@Before("@annotation(demo)")
public void doBefore(Demo demo) {// 这里可以直接获取到Demo注解的信息
}

切点表达式的参数匹配同样适用于 @within, @target, @args

怎样编写一个好的切点表达式?

要使切点的匹配性能达到最佳,编写表达式时,应该尽可能缩小匹配范围,切点表达式分为三大类:

  • 类型表达式:匹配某个特定切入点,如 execution
  • 作用域表达式:匹配某组切入点,如 within
  • 上下文表达式:基于上下文匹配某些切入点,如 thistarget@annotation

一个好的切点表达式应该至少包含前两种(类型和作用域)类型。
作用域表达式匹配的性能非常快,所以表达式中尽可能使用作用域类型。
上下文表达式可以基于切入点上下文匹配或在通知中绑定上下文。
单独使用类型表达式或上下文表达式比较消耗性能(时间或内存使用)。

三、切点表达式组合

使用 &&||! 来组合多个切点表达式,表示多个表达式“与”、“或”和“非”的逻辑关系。
这可以用来组合多种类型的表达式,来提升匹配效率。

// 匹配doExecution()切点表达式并且参数第一个为Account类型的方法
@Before("doExecution() && args(account,..)")
public void validateAccount(Account account) {// 自定义逻辑
}

四、附录

1. 常用注解

注解 描述
@Pointcut 指定切点表达式

2. 切点表达式类型

表达式类型 描述
execution 匹配方法切入点
within 匹配指定类型
this 匹配代理对象实例的类型
target 匹配目标对象实例的类型
args 匹配方法参数
bean 匹配 bean 的 id 或名称
@within 匹配类型是否含有注解
@target 匹配目标对象实例的类型是否含有注解
@annotation 匹配方法是否含有注解
@args 匹配方法参数类型是否含有注解

3. 示例代码

Gitee 仓库:https://gitee.com/code_artist/spring

最新文章关注 CodeArtist 码匠公众号。

更多:Spring高效实践专栏

第15章-Spring AOP切点表达式(Pointcut)详解相关推荐

  1. aop注解配置切点 spring_使用注解匹配Spring Aop切点表达式

    Spring中的类基本都会标注解,所以使用注解匹配切点可以满足绝大部分需求 主要使用@within()/@target @annotaton() @args()等... 匹配@Service类中的所有 ...

  2. Spring AOP 切面(Aspect)应用详解

    1. AOP 切面应用 下面是一个AOP切面的一个简单的应用实例 引入AOP依赖 <dependency><groupId>org.springframework.boot&l ...

  3. Spring Aop 切点表达式

    在Spring AOP 中,通常需要借助AspectJ 的切点表达式语言来定义切点.重要的是Spring 中仅支持AspectJ切点指示器的一个子集. Spring 支持的AspectJ的切点指示器 ...

  4. Spring AOP 切点表达式args与@args区别

    Spring AOP 中提供了丰富的切点表达式用于描述相对应的增强方法,其中@args是其中一种基于请求参数的增强逻辑. @args 表达式是用于限制目标方法参数的,与args类似.区别在于@args ...

  5. Spring AOP切点表达式详解

    1. 简介 面向对象编程,也称为OOP(即Object Oriented Programming)最大的优点在于能够将业务模块进行封装,从而达到功能复用的目的.通过面向对象编程,不同的模板可以相互组装 ...

  6. Spring AOP理论 +代理模式详解

    目录 1.理解AOP 1.1.什么是AOP 1.2.AOP体系与概念 1.3.Spring AOP 通知的执行顺序 2.代理模式 2.1.静态代理 2.2.静态代理的缺点 3.动态代理 JDK 动态代 ...

  7. java 切面详解_Spring AOP 切面表达式语法详解

    简述 由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且在Spring中,大部分需要使用AOP的业务场景也 ...

  8. 使用注解匹配Spring Aop切点表达式

    Spring中的类基本都会标注解,所以使用注解匹配切点可以满足绝大部分需求 主要使用@within()/@target @annotaton() @args()等... 匹配@Service类中的所有 ...

  9. spring aop切点表达式常见写法

最新文章

  1. 计算机软件考试预测,2020年计算机软件水平考试信息技术处理员预测试题及参考答案...
  2. 1503 - A PRIMARY KEY must include all columns in the table's partitioning function
  3. ipp 实现图像空间的转换
  4. Spring冲刺计划会议
  5. Linux云服务器安装Tomcat
  6. MongoDB非关系型数据库开发手册
  7. Android的隐式意图
  8. Minecraft InputFix
  9. Extjs3.3结合fckeditor2.6.6实现可视化编辑器(java版)
  10. JS Math方法、逻辑
  11. css中的伪元素:before :after与jQuery中的.before .after的区别
  12. 微型计算机地基本结构,微型计算机地基本结构.ppt
  13. linux办公软件wps字体,linux版wps-office安装缺少的字体
  14. wps qt linux,小试牛刀 WPS for Linux beta1文字试用
  15. 解决octavia failed to run
  16. 办公室电脑怎么设置共享文件夹?
  17. 玩转电脑|电脑回收站还能这么玩,自定义图标让你的回收站与众不同
  18. php注入过程详解,PHP注入代码详解
  19. 一个非常好用的数学函数图像生成工具
  20. Github文件夹下载到本地

热门文章

  1. InfoQ 2018回顾,2019展望
  2. vue 设计一个倒计时秒杀的组件
  3. 普源DS1102Z-E示波器,100MHz带宽
  4. 什么是网站,什么是网页,网页网站的关系
  5. 白话机器学习-用白话的方式通俗易懂的学习机器学习算法
  6. 如何直接把文件夹刻录到dvd光盘中
  7. AirServer在哪下载?如何免费使用教程
  8. Podman安装与运用
  9. php对接臻识摄像机
  10. lightgb原理_污染治理设施监管平台原理,智慧安全用电订制