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{}
  1. 常见 aspectj 切点用法
a. 底层切点实现是如何匹配的: 调用了 aspectj 的匹配方法
b. 比较关键的是它实现了 MethodMatcher 接口, 用来执行方法的匹配 matches 方法匹配
  1. aspectj 切点的局限性,实际的 @Transactional 切点实现
  2. StaticMethodMatcherPointcut 抽象类,实现其中的 matches 方法自定义匹配规则
  3. MergedAnnotations 注解工具类,可以判断是否含有相关注解
  • from 方法
    • 第一个参数传入方法或类返回封装了含有的所有注解类型的变量,
    • 第二个参数可以定义查找的策略,定义了一个静态内部枚举类 SearchStrategy 来实现。

DIRECT:只查找元素上直接声明的注解,不包括通过@Inherited继承的注解;

INHERITED_ANNOTATIONS:只查找元素直接声明或通过@Inherited继承的注解;

SUPERCLASS:查找元素直接声明或所有父类的注解;

TYPE_HIERARCHY:查找元素、所有父类以及实现的父接口的全部注解;

TYPE_HIERARCHY_AND_ENCLOSING_CLASSES:查找封闭类以及其子类。

通过源码可知,不指定时默认是 DIRECT:

    static MergedAnnotations from(AnnotatedElement element) {
        return from(element, MergedAnnotations.SearchStrategy.DIRECT);
    }
posted @ 2022-06-23 17:25  xy7112  阅读(102)  评论(0)    收藏  举报