spring 15 切点匹配
切点匹配规则
点击查看代码
public class S15 {
public static void main(String[] args) throws Exception {
//根据切点表达式判断当前方法是否匹配
AspectJExpressionPointcut pointcut1 = new AspectJExpressionPointcut();
pointcut1.setExpression("execution(* s151B())"); //设置切点表达式
System.out.println(pointcut1.matches(S151.class.getMethod("s151A"),S151.class));
System.out.println(pointcut1.matches(S151.class.getMethod("s151B"),S151.class));
System.out.println("============================================");
// 根据方法是否有此注解匹配
AspectJExpressionPointcut pointcut2 = new AspectJExpressionPointcut();
pointcut2.setExpression("@annotation(org.springframework.transaction.annotation.Transactional)");
System.out.println(pointcut2.matches(S151.class.getMethod("s151A"),S151.class));
System.out.println(pointcut2.matches(S151.class.getMethod("s151B"),S151.class));
System.out.println("============================================");
//根据类上或其父类或父接口是否有注解匹配,此时需要用到 StaticMethodMatcherPointcut
StaticMethodMatcherPointcut pointcut3 = new StaticMethodMatcherPointcut() {
//定义匹配规则
@Override
public boolean matches(Method method, Class<?> targetClass) {
//注解工具类,判断是否含有相关注解
//1.判断方法
MergedAnnotations annotations = MergedAnnotations.from(method);
if (annotations.isPresent(Transactional.class)) {
return true;
}
//2.判断类
MergedAnnotations annotations2 = MergedAnnotations
//设置多层结构查找,不仅在当前类上查找注解,还有父类或接口,一直到顶层
.from(targetClass, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
if (annotations2.isPresent(Transactional.class)) {
return true;
}
return false;
}
};
System.out.println(pointcut3.matches(S151.class.getMethod("s151A"),S151.class));
System.out.println(pointcut3.matches(S151.class.getMethod("s151B"),S151.class));
System.out.println(pointcut3.matches(S152.class.getMethod("s152A"), S152.class));
System.out.println(pointcut3.matches(S152.class.getMethod("s152B"), S152.class));
System.out.println(pointcut3.matches(S153.class.getMethod("s153A"),S153.class));
System.out.println(pointcut3.matches(S153.class.getMethod("s153B"),S153.class));
}
}
class S151 {
@Transactional
public void s151A() {
}
public void s151B() {
}
}
@Transactional
class S152 {
public void s152A() {
}
public void s152B() {
}
}
class S153 implements S154{
public void s153A() {
}
public void s153B() {
}
}
interface S154 extends S155{}
@Transactional
interface S155{}
- 常见 aspectj 切点用法
a. 底层切点实现是如何匹配的: 调用了 aspectj 的匹配方法
b. 比较关键的是它实现了 MethodMatcher 接口, 用来执行方法的匹配 matches 方法匹配
- aspectj 切点的局限性,实际的 @Transactional 切点实现
StaticMethodMatcherPointcut
抽象类,实现其中的 matches 方法自定义匹配规则MergedAnnotations
注解工具类,可以判断是否含有相关注解
from
方法- 第一个参数传入方法或类返回封装了含有的所有注解类型的变量,
- 第二个参数可以定义查找的策略,定义了一个静态内部枚举类
SearchStrategy
来实现。
DIRECT:只查找元素上直接声明的注解,不包括通过@Inherited继承的注解;
INHERITED_ANNOTATIONS:只查找元素直接声明或通过@Inherited继承的注解;
SUPERCLASS:查找元素直接声明或所有父类的注解;
TYPE_HIERARCHY:查找元素、所有父类以及实现的父接口的全部注解;
TYPE_HIERARCHY_AND_ENCLOSING_CLASSES:查找封闭类以及其子类。
- 封闭类是 JDK17 的新特性,可参考 详解 Java 17中的新特性:“密封类”
- @Inherited 是一个元注解,可以使其修饰的注解具有传递性,参考:https://blog.csdn.net/gongm24/article/details/121320540
通过源码可知,不指定时默认是 DIRECT:
static MergedAnnotations from(AnnotatedElement element) {
return from(element, MergedAnnotations.SearchStrategy.DIRECT);
}