Spring AOP切入点表达式

AOP切入点表达式

1. 之前写法的问题

我们之前写切入点是这样的:

execution(void com.yyl.dao.BookDao.update())

看着还行,但是这样一个方法一配置会产生一个问题:

问题1:按照上面的形式去编写切入点,一个两个还行,要是该类中的很多方法都要编写AOP是十分麻烦的,那么我们该如何简化切入点表达式中包名和参数类型书写?


还是刚才的update函数,虽然我们编程是按照接口编程,但是最后运行还是实现类,所以下面两个对于接口与实现类的update描述方式都是对的

image-20220724091033753

  • 描述方式一:执行com.yyl.dao包下的BookDao接口中的无参数update方法
execution(void com.yyl.dao.BookDao.update())
  • 描述方式二:执行com.yyl.dao.impl包下的BookDaoImpl类中的无参数update方法
execution(void com.yyl.dao.impl.BookDaoImpl.update())

问题2:那么这样又会产生一个问题,两种混用的话最后看起来会很乱,到底用那种方式去写呢?

下面就引入了AOP切入点表达式,见名知意,他和其他的xx表达式差不多,都有固定格式、通配符等概念,可以帮我们简化AOP切片编程的书写,也可以帮我们约定书写格式规范:

2. 切入点表达式概念

首先回顾一下什么是切入点?

  • 切入点:要进行增强的方法

那么切入点表达式就简单了,他就是一种切入点的描述方式

  • 切入点表达式:要进行增强的方法的描述方式

3. 语法格式

3.1 切入点表达式标准格式:

动作关键字(访问修饰符  返回值  包名./接口名.方法名(参数) 异常名)

其中的各部分说明如下:

参数 说明
动作关键字 描述切入点的行为动作,例如execution表示执行到指定切入点
访问修饰符 public,private等,可以省略
返回值 写返回值类型
包名 多级包使用点连接
类/接口名
方法名
参数 直接写参数的类型,多个类型用逗号隔开
异常名 方法定义中抛出指定异常,可以省略

例如:

execution(public User com.yyl.service.UserService.QueryById(int))

3.2 通配符

切入点表达式也有通配符的概念

通配符目的:可以使用通配符描述切入点,快速描述。

有下面三个常用的通配符:

  • * :单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现

例如:匹配com.yyl包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法

execution(public * com.yyl.*.UserService.find*(*))
  • .. :多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写

例如:匹配com包下的任意包中的UserService类或接口中所有名称为findById的方法

execution(public User com..UserService.findById(..))
  • +:专用于匹配子类类型

例如:匹配包下的XXXService的所有方法

execution(* *..*Service+.*(..))

3.3 书写技巧

  • 所有代码按照标准规范开发,否则以下技巧全部失效
  • 描述切入点通常描述接口,而不描述实现类
  • 访问控制修饰符针对接口开发均采用public描述(可省略访问控制修饰符描述
  • 返回值类型对于增删改类使用精准类型加速匹配,对于查询类使用*通配快速描述
  • 包名书写尽量不使用…匹配,效率过低,常用*做单个包描述匹配,或精准匹配
  • 接口名/类名书写名称与模块相关的采用*匹配,例如UserService书写成*Service,绑定业务层接口名
  • 方法名书写以动词进行精准匹配,名词采用*匹配,例如getById书写成getBy*,selectAll书写成selectAll
  • 参数规则较为复杂,根据业务方法灵活调整
  • 通常**不使用异常作为匹配**规则

4. 实战演练

还是上面的update函数,你想想还能怎么写

@Pointcut("execution(void com.yyl.dao.BookDao.update())")
@Pointcut("execution(void com.yyl.dao.impl.BookDaoImpl.update())")
@Pointcut("execution(void com.*.*.*.update())")
@Pointcut("execution(* *..*(..))")
@Pointcut("execution(* *..*e(..))")
@Pointcut("execution(void com..*())")

但是要注意,下面这样是不行的update(*),这样说明里面有参数

@Pointcut("execution(* com.yyl.dao.impl.BookDaoImpl.update(*))")    //no

其他的没问题
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45525272/article/details/125955860