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. Codeforces 710F - String Set Queries(AC 自动机)

    题面传送门 题意:强制在线的 AC 自动机. \(n,\sum|s|\leq 3\times 10^5\) 如果不是强制在线那此题就是道 sb 题,加了强制在线就不那么 sb 了. 这里介绍两种做法: ...

  2. Codeforces 1063F - String Journey(后缀数组+线段树+dp)

    Codeforces 题面传送门 & 洛谷题面传送门 神仙题,做了我整整 2.5h,写篇题解纪念下逝去的中午 后排膜拜 1 年前就独立切掉此题的 ymx,我在 2021 年的第 5270 个小 ...

  3. Atcoder Grand Contest 008 E - Next or Nextnext(乱搞+找性质)

    Atcoder 题面传送门 & 洛谷题面传送门 震惊,我竟然能独立切掉 AGC E 难度的思维题! hb:nb tea 一道 感觉此题就是找性质,找性质,再找性质( 首先看到排列有关的问题,我 ...

  4. 【软连接已存在,如何覆盖】ln: failed to create symbolic link ‘file.txt’: File exists

    ln -s 改成 ln -sf f在很多软件的参数中意味着force ln -sf /usr/bin/bazel-1.0.0 /usr/bin/bazel

  5. Oracle——检查数据库是否正常运行,如果没有,并重启数据库

    1.su oracle  切换到linux的oracle账号 需要使用 su -oracle,而不是su oracle;原因是: 先执行exit退出,再重新切换 2.打开数据库监听 lsnrctl l ...

  6. 自定义char类型字符,django中事务

    自定义char类型字符 # 自定义char类型,继承Field父类 class MyCharField(Field): def __init__(self, max_length, *args, ** ...

  7. EPOLL原理详解(图文并茂)

    文章核心思想是: 要清晰明白EPOLL为什么性能好. 本文会从网卡接收数据的流程讲起,串联起CPU中断.操作系统进程调度等知识:再一步步分析阻塞接收数据.select到epoll的进化过程:最后探究e ...

  8. C语言中的main函数的参数解析

    main()函数既可以是无参函数,也可以是有参的函数.对于有参的形式来说,就需要向其传递参数.但是其它任何函数均不能调用main()函数.当然也同样无法向main()函数传递,只能由程序之外传递而来. ...

  9. 外网无法访问hdfs文件系统

    由于本地测试和服务器不在一个局域网,安装的hadoop配置文件是以内网ip作为机器间通信的ip. 在这种情况下,我们能够访问到namenode机器, namenode会给我们数据所在机器的ip地址供我 ...

  10. Linux:-e、-d、-f、-L、-r、-w、-x、-s、-h、

    -e filename 如果 filename存在,则为真 -d filename 如果 filename为目录,则为真 -f filename 如果 filename为常规文件,则为真 -L fil ...