【JavaWeb】Day73.Spring——AOP进阶(切入点表达式)

切入点表达式

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

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

常见形式:

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

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

execution

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

execution(访问修饰符?  返回值  包名.类名.?方法名(方法参数) throws 异常?)

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

  • 访问修饰符:可省略(比如: public、protected)
  • 包名.类名: 可省略
  • throws 异常:可省略(注意是方法上声明抛出的异常,不是实际抛出的异常)

示例:

~~~java
@Before("execution(void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
~~~

可以使用通配符描述切入点

  • `*` :单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分
  • `..` :多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数

切入点表达式的语法规则:

1. 方法的访问修饰符可以省略

2. 返回值可以使用`*`号代替(任意返回值类型)

3. 包名可以使用`*`号代替,代表任意包(一层包使用一个`*`)

4. 使用`..`配置包名,标识此包以及此包下的所有子包

5. 类名可以使用`*`号代替,标识任意类

6. 方法名可以使用`*`号代替,表示任意方法

7. 可以使用 `*`  配置参数,一个任意类型的参数

8. 可以使用`..` 配置参数,任意个任意类型的参数

切入点表达式示例

省略方法的修饰符号

 ~~~java
  execution(void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))
  ~~~

 使用`*`代替返回值类型

~~~java
  execution(* com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))
  ~~~

使用`*`代替包名(一层包使用一个`*`)

~~~java
  execution(* com.itheima.*.*.DeptServiceImpl.delete(java.lang.Integer))
  ~~~

使用`..`省略包名

~~~java
  execution(* com..DeptServiceImpl.delete(java.lang.Integer))    
  ~~~

 使用`*`代替类名

~~~java
  execution(* com..*.delete(java.lang.Integer))   
  ~~~

使用`*`代替方法名

~~~java
  execution(* com..*.*(java.lang.Integer))   
  ~~~

使用 `*` 代替参数

```java
  execution(* com.itheima.service.impl.DeptServiceImpl.delete(*))
  ```

使用`..`省略参数

~~~java
  execution(* com..*.*(..))
  ~~~

注意事项:

- 根据业务需要,可以使用 且(&&)、或(||)、非(!) 来组合比较复杂的切入点表达式。

```java
  execution(* com.itheima.service.DeptService.list(..)) || execution(* com.itheima.service.DeptService.delete(..))

切入点表达式的书写建议:

  1. 所有业务方法名在命名时尽量规范,方便切入点表达式快速匹配。如:查询类方法都是 find 开头,更新类方法都是update开头
  2. 描述切入点方法通常基于接口描述,而不是直接描述实现类,增强拓展性
  3. 在满足业务需要的前提下,尽量缩小切入点的匹配范围。如:包名匹配尽量不使用 ..,使用 * 匹配单个包

@annotation

        如果我们要匹配多个无规则的方法,比如:list()和 delete()这两个方法。这个时候我们基于execution这种切入点表达式来描述就不是很方便了。而在之前我们是将两个切入点表达式组合在了一起完成的需求,这个是比较繁琐的。

        我们可以借助于另一种切入点表达式annotation来描述这一类的切入点,从而来简化切入点表达式的书写。

实现步骤:

1. 编写自定义注解

2. 在业务类要做为连接点的方法上添加自定义注解

自定义注解:MyLog

~~~java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
}
~~~

业务类:DeptServiceImpl

~~~java
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;

    @Override
    @MyLog //自定义注解(表示:当前方法属于目标方法)
    public List<Dept> list() {
        List<Dept> deptList = deptMapper.list();
        //模拟异常
        //int num = 10/0;
        return deptList;
    }

切面类

~~~java
@Slf4j
@Component
@Aspect
public class MyAspect6 {
    //针对list方法、delete方法进行前置通知和后置通知

    //前置通知
    @Before("@annotation(com.itheima.anno.MyLog)")
    public void before(){
        log.info("MyAspect6 -> before ...");
    }

    //后置通知
    @After("@annotation(com.itheima.anno.MyLog)")
    public void after(){
        log.info("MyAspect6 -> after ...");
    }
}
~~~

重启SpringBoot服务,测试查询所有部门数据,查看控制台日志:

总结:

execution切入点表达式

  - 根据我们所指定的方法的描述信息来匹配切入点方法,这种方式也是最为常用的一种方式

  - 如果我们要匹配的切入点方法的方法名不规则,或者有一些比较特殊的需求,通过execution切入点表达式描述比较繁琐

annotation 切入点表达式

  - 基于注解的方式来匹配切入点方法。这种方式虽然多一步操作,我们需要自定义一个注解,但是相对来比较灵活。我们需要匹配哪个方法,就在方法上加上对应的注解就可以了

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值