1.根据方法名匹配
public class A016copy {
public static void main(String[] args) throws NoSuchMethodException {
AspectJExpressionPointcut pointcut=new AspectJExpressionPointcut();
pointcut.setExpression("execution(* bar())");
System.out.println(pointcut.matches(T1.class.getMethod("foo"), T1.class));
System.out.println(pointcut.matches(T1.class.getMethod("bar"), T1.class));
}
static class T1 {
@Transactional
public void foo() {
}
public void bar() {
}
}
@Transactional
static class T2 {
public void foo() {
}
}
@Transactional
interface I3 {
void foo();
}
static class T3 implements I3 {
public void foo() {
}
}
}
("execution(* bar())")匹配bar方法
输出两个matches,应该只匹配bar方法,所以应该false第二个true;
2.根据注解匹配
AspectJExpressionPointcut pointcut2=new AspectJExpressionPointcut();
pointcut2.setExpression("@annotation(org.springframework.transaction.annotation.Transactional)");
System.out.println(pointcut2.matches(T1.class.getMethod("foo"), T1.class));
System.out.println(pointcut2.matches(T1.class.getMethod("bar"), T1.class));
foo有@Transactional注解,所以应该输出true和false
3. @Transactional底层实现
@Transactional底层并不是AspectJExpressionPointcut实现,因为@Transactional用法比较复杂,除了加在方法上还可以加在类上。
StaticMethodMatcherPointcut pt3 = new StaticMethodMatcherPointcut() {
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 检查方法上是否加了 Transactional 注解
MergedAnnotations annotations = MergedAnnotations.from(method);
if (annotations.isPresent(Transactional.class)) {
return true;
}
// 查看类上是否加了 Transactional 注解
annotations = MergedAnnotations.from(targetClass);
if (annotations.isPresent(Transactional.class)) {
return true;
}
return false;
}
};
System.out.println(pt3.matches(T1.class.getMethod("foo"), T1.class));
System.out.println(pt3.matches(T1.class.getMethod("bar"), T1.class));
System.out.println(pt3.matches(T2.class.getMethod("foo"), T2.class));
System.out.println(pt3.matches(T3.class.getMethod("foo"), T3.class));
}
先判断方法上是否加了注解,再判断类上是否加了注解,前三个分别输出true,false,true,比较简单,最后这个应该也输出true但输出了false因为MergedAnnotations.from(method);默认只查一层。改为annotations = MergedAnnotations.from(targetClass, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);就好了。
总结:
a. 底层切点实现是如何匹配的: 调用了 aspectj 的匹配方法
b. 比较关键的是它实现了 MethodMatcher 接口, 用来执行方法的匹配