1. AOP 概念篇

今天介绍 Pointcut 的表达式

通配符

常见的通配符如下

..

含义一:方法表达式中、代表任意数量的参数

@Service
public class HelloService {
public void sayHi(String name) {
System.out.println("hi," + name);
}
public void sayHi(String firstName, String lastName) {
System.out.println("hi," + firstName + lastName);
}
}
@Pointcut("execution(public void com.example.junitspringboot.service.HelloService.sayHi(..))")
public void pointcut(){}

那么上面的 Pointcut 表达式就能将 HelloService 中的两个连接点都包括进去。

  • 连接点:程序执行的某个特定位置,比如某个方法调用前、调用后,方法抛出异常后,对类成员的访问以及异常处理程序块的执行等。一个类或一段程序代码拥有一些具有边界性质的特定点,这些代码中的特定点就是连接点。它自身还可以嵌套其他的 Joinpoint。AOP 中的 Joinpoint 可以有多种类型:构造方法调用,字段的设置和获取,方法的调用,方法的执行,异常的处理执行,类的初始化。Spring 仅支持方法执行类型的 Joinpoint。

含义二:类定义表达式中、代表任意子包

@Component
@Aspect
public class ServiceAop { @Pointcut("execution(public void com.example.junitspringboot..HelloService.sayHi(..))")
public void pointcut(){} @Around("pointcut()")
public Object before(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("before");
return proceedingJoinPoint.proceed();
}
}
// 注意包名
package com.example.junitspringboot.service.inner; import org.springframework.stereotype.Service; @Service("innerHelloService")
public class HelloService {
public void sayHi(String firstName, String lastName) {
System.out.println("hi," + firstName + lastName);
}
}
// 注意包名
package com.example.junitspringboot.service; public class HelloService { public void sayHi(String name) {
System.out.println("hi," + name);
}
}

+

匹配给定类及其子类

public interface Person {
void say();
}
@Service
public class Man implements Person{
@Override
public void say() {
System.out.println("man");
}
}
@Service
public class Woman implements Person {
@Override
public void say() {
System.out.println("woman");
}
}
@Pointcut("within(com.example.junitspringboot.service.Person+)")
public void pointcut(){}

那么接口 Person 的子类所有实现的方法都会被增强。

*

匹配任意数量的字符

// com.example.junitspringboot.service 包所有的类的所有方法
@Pointcut("within(com.example.junitspringboot.service.*)")
public void pointcut1(){} // 所有以 say 开头的方法
@Pointcut("execution(* say*(..))")
public void pointcut2(){}

execution

使用得最多的表达式、用于指定方法的执行。? 表示非必填

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?
name-pattern(param-pattern) throws-pattern?)
  • modifiers-pattern? 表示修饰符、如 public、protected
  • ret-type-pattern 返回类型、必填。 如果使用通配符 * 代表任意的返回类型
  • declaring-type-pattern? 表示声明方法的类。
  • name-pattern 表示方法名。
  • param-pattern 表示方法参数、如果使用通配符 .. 则代表任意参数
  • throws-pattern? 表示方法抛出的异常

例子

execution(public * com.example..say*(..))
  • 修饰符为 public
  • 任意返回类型
  • 在 com.example 包或者其子包下
  • 方法名称以 say 开头
  • 任意参数
@Pointcut("execution( * say*(..))")
  • 任意返回类型
  • 方法名称以 say 开头
  • 任意参数
@Pointcut("execution(* *(..) throws Exception)")
  • 方法声明抛出 Exception 的任意方法

within

指定特定类型、类型中所有的方法都被拦截。

@Pointcut("within(com.example.junitspringboot.service.Person)")
  • Person 类所有外部的方法调用都被拦截
@Pointcut("within(com.example.junitspringboot.service.Person+)")
  • Person 类及其子类所有外部的方法调用都被拦截
@Pointcut("within(com.example.junitspringboot.service..*)"
  • 所有在 com.example.junitspringboot.service 包以及子包下的所有类的所有外部调用方法

this

this通过判断代理类是否按类型匹配指定类来决定是否和切点匹配。 用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配。 this中使用的表达式必须是类型全限定名,不支持通配符。

public class ServiceAop implements Ordered {
@Pointcut("this(com.example.junitspringboot.service.ISwimming)")
public void thisPointcut(){}
@Before("thisPointcut()")
public void before(JoinPoint joinPoint) {
System.out.println("before");
}
@Override
public int getOrder() {
return 1;
}
}
// 使用引介使 Man 也实现 ISwimming 接口
@Component
@Aspect
public class IntroductionAop implements Ordered {
@DeclareParents(value = "com.example.junitspringboot.service.Man", defaultImpl = Swimming.class)
public ISwimming swimming;
@Override
public int getOrder() {
return 0;
}
}
// 微信公众号:CoderLi
public interface ISwimming {
void swim();
}
// 微信公众号:CoderLi
@Service
public class Man implements Person{
@Override
public void say() {
System.out.println("man");
}
}
ConfigurableApplicationContext context = SpringApplication.run(JunitSpringBootApplication.class, args);
context.getBean(Man.class).say();
((ISwimming) context.getBean(Man.class)).swim();

当我们调用 swim 方法的时候、会被拦截增强。当我们调用 say 方法的时候、同样也会被拦截增强,这个就是 this 会将代理类实现的其他接口的方法也会被拦截增强

target

target 通过判断目标类是否按类型匹配指定类来决定连接点是否匹配. 用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;

    @Pointcut("target(com.example.junitspringboot.service.ISwimming)")

同样也是上面的例子。修改切点表达式为 target 、say 方法不再被拦截增强。

args

用来匹配参数

@Pointcut("args(..)")
  • 匹配任意参数的方法
@Pointcut("args()")
  • 匹配任何不带参数的方法

@target

匹配当被代理的目标对象对应的类型及其父类型上拥有指定的注解时

@Pointcut("@target(com.example.junitspringboot.anno.AopFlag) && within(com.example.junitspringboot..*)")
  • 匹配在包 com.example.junitspringboot..* 下所有被 AopFlag 修饰的类的所有方法

@args

@args匹配被调用的方法上含有参数,且对应的参数类型上拥有指定的注解的情况。

@Pointcut("@args(com.example.junitspringboot.anno.AopFlag)")
// 微信公众号:CoderLi
@AopFlag
public class Data {
}
public interface Person {
void say(Data data);
}

@within

@within用于匹配被代理的目标对象对应的类型或其父类型拥有指定的注解的情况,但只有在调用拥有指定注解的类上的方法时才匹配。

   @Pointcut("@within(com.example.junitspringboot.anno.AopFlag) && within(com.example.junitspringboot..*)")

这个功能上貌似跟 @target 有点像了

@annotation

也是比较常用的一个注解、用于匹配方法上拥有指定注解的情况。

@Pointcut("@annotation(com.example.junitspringboot.anno.AopFlag) && within(com.example.junitspringboot..*)")

bean

Spring 特有的一个表达式。

@Pointcut("bean(man)")

拦截该 bean 的所有方法

10 种切点的表达式介绍完毕

Pointcut 表达式的更多相关文章

  1. spring aop中pointcut表达式完整版

    spring aop中pointcut表达式完整版 本文主要介绍spring aop中9种切入点表达式的写法 execute within this target args @target @with ...

  2. Spring Aop(三)——Pointcut表达式介绍

    转发地址:https://www.iteye.com/blog/elim-2395255 3 Pointcut表达式介绍 3.1 表达式类型 标准的Aspectj Aop的pointcut的表达式类型 ...

  3. pointcut 表达式的含义

    execution(* com.spring.dao.*.add*(..)) 第一个*表示任意返回值 第二个*表示com.spring.dao包中所有类 第三个*表示以add开头的所有方法 (..)表 ...

  4. Spring AOP 切点(pointcut)表达式

    这遍文章将介绍Spring AOP切点表达式(下称表达式)语言,首先介绍两个面向切面编程中使用到的术语. 连接点(Joint Point):广义上来讲,方法.异常处理块.字段这些程序调用过程中可以抽像 ...

  5. Spring AOP AspectJ Pointcut 表达式例子

    主要来源:http://howtodoinjava.com/spring/spring-aop/writing-spring-aop-aspectj-pointcut-expressions-with ...

  6. aop point-cut表达式

    好多博客写的云里雾里,大多都有一点毛病.大家还是以官网为准 @官网文档 官网截图 modifiers-pattern:修饰符 ret-type-pattern:方法返回类型 declaring-typ ...

  7. Spring AOP 之二:Pointcut注解表达式

    简介 在Spring AOP概述中我们重点注意的是AOP的整体流程和Advice,简化了一些其他的东西,其中就有一些对灵活应用Spring AOP很重要的知识点,例如Pointcut表达式,下面就介绍 ...

  8. Spring入门之AOP实践:@Aspect + @Pointcut + @Before / @Around / @After

    零.准备知识 1)AOP相关概念:Aspect.Advice.Join point.Pointcut.Weaving.Target等. ref: https://www.cnblogs.com/zha ...

  9. 【Spring AOP】切入点表达式(四)

    一.切入点指示符 切入点指示符用来指示切入点表达式目的,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指示符如下: execution:用于匹配方 ...

随机推荐

  1. CF1175G

    叉姐牛逼. \(f_{k,i} = \min_{0\leq j <i}{f_{k - 1,j} + RMQ(j + 1,i) * (i - j)}\) 我们考虑在序列上分治一波. 按照\(m\) ...

  2. Sums gym100753M

    Sums gym100753M 同余最短路模板,然而这个东西貌似也可以做去年D1T2 首先我们选择一个模数作为基准,然后剩下的这样连边: 对于一个面值为 x 的硬币 ,当前在 u 这个点(感性理解一下 ...

  3. bitset 的妙用:乱搞字符串匹配

    最近碰到了几次 bitset 乱搞字符串匹配的情况,故写文以记之. 1. 算法简介 核心思想:假设文本串为 \(s\),则对字符集中的每一个字符 \(c\) 开一个大小为 \(|s|\) 的 bits ...

  4. 【Python小试】统计一条核酸序列中频数非0或为2的双核苷酸

    概念 双核苷酸由任意2个碱基组成 测试1 dna = "AATGATGAACGAC" #一一列举 dinucleotides = ['AA','AT','AG','AC', 'TA ...

  5. 31-Longest Common Prefix

    Longest Common Prefix My Submissions Difficulty: Easy Write a function to find the longest common pr ...

  6. C++栈溢出

    先看一段代码 #include<iostream> using namespace std; #define n 510 void sum(int a,int b) { cout<& ...

  7. 【Redis】Sentinel 哨兵模式

    Sentinel(哨兵模式) 目录 Sentinel(哨兵模式) 哨兵模式的三个定时任务 Sentinel(哨兵)与Sentinel .主服务器.从服务器之间的连接 检测下线状态 选择领头 Senti ...

  8. 100个Shell脚本——【脚本2】截取字符串

    [脚本2]截取字符串 一.脚本 现有一个字符串如下: http://www.aaa.com/root/123.htm 请根据以下要求截取出字符串中的字符: 1.取出www.aaa.com/root/1 ...

  9. HttpClient连接池设置引发的一次雪崩

    事件背景 我在凤巢团队独立搭建和运维的一个高流量的推广实况系统,是通过HttpClient 调用大搜的实况服务.最近经常出现Address already in use (Bind failed)的问 ...

  10. 【Linux】【Basis】块存储,文件存储,对象存储

    1. 块存储: 定义:这种接口通常以QEMU Driver或者Kernel Module的方式存在,这种接口需要实现Linux的Block Device的接口或者QEMU提供的Block Driver ...