this:
Spring Aop是基于代理的,this就表示代理对象。this类型的Pointcut表达式的语法是this(type),当生成的代理对象可以转换为type指定的类型时则表示匹配。基于JDK接口的代理和基于CGLIB的代理生成的代理对象是不一样的。(注意和上面within的区别)
// 这样子,就可以拦截到AService所有的子类的所有外部调用方法 @Pointcut("this(com.fsx.run.service.AService*)") public void pointCut() { }
target:
Spring Aop是基于代理的,target则表示被代理的目标对象。当被代理的目标对象可以被转换为指定的类型时则表示匹配。
注意:和上面不一样,这里是target,因此如果要切入,只能写实现类了
@Pointcut("target(com.fsx.run.service.impl.AServiceImpl)") public void pointCut() { }
args:
args用来匹配方法参数的。
1、“args()”匹配任何不带参数的方法。
2、“args(java.lang.String)”匹配任何只带一个参数,而且这个参数的类型是String的方法。
3、“args(…)”带任意参数的方法。
4、“args(java.lang.String,…)”匹配带任意个参数,但是第一个参数的类型是String的方法。
5、“args(…,java.lang.String)”匹配带任意个参数,但是最后一个参数的类型是String的方法。
@Pointcut("args()") public void pointCut() { }
这个匹配的范围非常广,所以一般和别的表达式结合起来使用
@target:
@target匹配当被代理的目标对象对应的类型及其父类型上拥有指定的注解时。
//能够切入类上(非方法上)标准了MyAnno注解的所有外部调用方法 @Pointcut("@target(com.fsx.run.anno.MyAnno)") public void pointCut() { }
@args:
@args匹配被调用的方法上含有参数,且对应的参数类型上拥有指定的注解的情况。
例如:
// 匹配**方法参数类型上**拥有MyAnno注解的方法调用。如我们有一个方法add(MyParam param)接收一个MyParam类型的参数,而MyParam这个类是拥有注解MyAnno的,则它可以被Pointcut表达式匹配上 @Pointcut("@args(com.fsx.run.anno.MyAnno)") public void pointCut() { }
@within:
@within用于匹配被代理的目标对象对应的类型或其父类型拥有指定的注解的情况,但只有在调用拥有指定注解的类上的方法时才匹配。
“@within(com.fsx.run.anno.MyAnno)”匹配被调用的方法声明的类上拥有MyAnno注解的情况。比如有一个ClassA上使用了注解MyAnno标注,并且定义了一个方法a(),那么在调用ClassA.a()方法时将匹配该Pointcut;如果有一个ClassB上没有MyAnno注解,但是它继承自ClassA,同时它上面定义了一个方法b(),那么在调用ClassB().b()方法时不会匹配该Pointcut,但是在调用ClassB().a()时将匹配该方法调用,因为a()是定义在父类型ClassA上的,且ClassA上使用了MyAnno注解。但是如果子类ClassB覆写了父类ClassA的a()方法,则调用ClassB.a()方法时也不匹配该Pointcut。
@annotation:使用得也比较多
@annotation用于匹配方法上拥有指定注解的情况。
// 可以匹配所有方法上标有此注解的方法 @Pointcut("@annotation(com.fsx.run.anno.MyAnno)") public void pointCut() { }
我们还可以这么写,非常方便的获取到方法上面的注解
@Before("@annotation(myAnno)") public void doBefore(JoinPoint joinPoint, MyAnno myAnno) { System.out.println(myAnno); //@com.fsx.run.anno.MyAnno() System.out.println("AOP Before Advice..."); }
reference pointcut:切入点引用(使用得非常多)
@Aspect public class HelloAspect { @Pointcut("execution(* com.fsx.service.*.*(..)) ") public void point() { } // 这个就是一个`reference pointcut` 甚至还可以这样 @Before("point1() && point2()") @Before("point()") public void before() { System.out.println("this is from HelloAspect#before..."); } }
bean: 这是Spring增加的一种方法,spring独有
bean用于匹配当调用的是指定的Spring的某个bean的方法时。
1、“bean(abc)”匹配Spring Bean容器中id或name为abc的bean的方法调用。
2、“bean(user*)”匹配所有id或name为以user开头的bean的方法调用。
// 这个就能切入到AServiceImpl类的素有的外部调用的方法里 @Pointcut("bean(AServiceImpl)") public void pointCut() { }
类型匹配语法
*:匹配任何数量字符;
…:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。
+:匹配指定类型的子类型;仅能作为后缀放在类型模式后边。
java.lang.String 匹配String类型; java.*.String 匹配java包下的任何“一级子包”下的String类型; 如匹配java.lang.String,但不匹配java.lang.ss.String java..* 匹配java包及任何子包下的任何类型。如匹配java.lang.String、java.lang.annotation.Annotation java.lang.*ing 匹配任何java.lang包下的以ing结尾的类型; java.lang.Number+ 匹配java.lang包下的任何Number的子类型; 如匹配java.lang.Integer,也匹配java.math.BigInteger
表达式的组合
表达式的组合其实就是对应的表达式的逻辑运算,与、或、非。可以通过它们把多个表达式组合在一起。
1、“bean(userService) && args()”匹配id或name为userService的bean的所有无参方法。
2、“bean(userService) || @annotation(MyAnnotation)”匹配id或name为userService的bean的方法调用,或者是方法上使用了MyAnnotation注解的方法调用。
3、“bean(userService) && !args()”匹配id或name为userService的bean的所有有参方法调用。