【问题标题】:Pointcut for annotated methods or methods in annotated classes带注释的方法或带注释的类中的方法的切入点
【发布时间】:2016-03-23 10:18:05
【问题描述】:

我需要为用@X 注释的类中的方法或用@X 注释的方法的切入点。我还需要注释对象。如果类和方法都被注释了我更喜欢将方法注释作为参数

我尝试了以下方法,这会产生“不一致的绑定”警告。 (为什么不直接将它们设置为 null?)

@Around("@annotation(methodLevelX) || @within(classLevelX)")
public Object advise(ProceedingJoinPoint pjp, X methodLevelX, X classLevelX)

以下创建了一个“参数 x 跨 '||' 的模糊绑定在切入点”警告。 (我认为这不一定有意义:为什么不绑定第一个短路评估?)

@Around("@annotation(x) || @within(x)")
public Object advise(ProceedingJoinPoint pjp, X x)

如果存在类和方法注释,则将先前的尝试一分为二自然会导致两个方法调用。

我知道我可以通过反射获得方法和类,并通过这样的切入点获得所需的注释:

@Around("@annotation(com.package.X) || @within(com.package.X)")

但我不想这样做。

有没有“一个切入点,一个方法,一个注解参数”,不需要反射的我的需求的解决方案?

【问题讨论】:

    标签: java spring aop spring-aop


    【解决方案1】:

    不完全是,但差不多。您将需要两个切入点、两个建议,但您可以将工作委托给一个方法。下面是它的样子:

    @Aspect
    public class AnyAspectName {
    
        @Pointcut("execution(@X * *.*(..))")
        void annotatedMethod() {}
    
        @Pointcut("execution(* (@X *).*(..))")
        void methodOfAnnotatedClass() {}
    
        @Around("annotatedMethod() && @annotation(methodLevelX)")
        public Object adviseAnnotatedMethods(ProceedingJoinPoint pjp, X methodLevelX) 
                throws Throwable {
            return aroundImplementation(pjp, methodLevelX);
        }
    
        @Around("methodOfAnnotatedClass() && !annotatedMethod() && @within(classLevelX)")
        public Object adviseMethodsOfAnnotatedClass(ProceedingJoinPoint pjp, X classLevelX) 
                throws Throwable {
            return aroundImplementation(pjp, classLevelX);
        }
    
        public Object aroundImplementation(ProceedingJoinPoint pjp, X annotation) 
                throws Throwable {
            return pjp.proceed();
        }
    
    }
    

    请注意,除了将@annotation()@within() 切入点分开之外,我还对生成的切入点添加了限制,这样它们就不会太宽泛。我想你想要 method execution 连接点,所以我添加了所需的切入点表达式,将其限制为方法执行。他们是匹配的

    1. 执行带有 @X 注释的任何方法,任何类中的任何返回类型都在任何包中用于第一个建议
    2. 在任何带有@X注解的类中执行任何返回类型的任何方法第二次。

    进一步限制 @within(X)@annotation(X) 会派上用场,因为 @within(X) 本身会匹配

    关联代码在类型中定义的任何连接点 X 类型的注解

    包括方法执行方法调用构造函数执行构造函数调用预初始化静态初始化初始化字段设置字段获取exception-handlerlock 类型的连接点(但并非所有连接点都对 around 通知 有效)。同样,@annotation(X) 本身意味着

    主题具有X 类型注释的任何连接点

    这也可能意味着前面提到的大部分连接点,具体取决于注释的目标类型。

    【讨论】:

    • 谢谢你的回答,我会试试你的想法。我对@annotation(x) 尽可能多地捕获没问题,因为我只会有意识地将我的注释放在方法上,如果不是放在类型上的话。
    • 昨天我发现了另一种解决方案:它也适用于两个建议:一个只是“@annotation(x)”,第二个是“@within(x) && !@annotation(at.X) && !execution(*.new(..))".
    • @annotation(x) 仍将匹配“方法调用”和“方法执行”连接点,因此您的建议可能会被调用两次。我认为限制这些宽泛的切入点表达式总是好的,比如 '@within` 或 @anotation()
    • 你说得对,我忘了在同时存在类级别和方法级别注释的情况下包含该部分。我想在这种情况下最好给方法级注释优先级。
    • 我找不到任何关于“方法调用”和“方法执行”之间区别的具体信息。您是否有更多关于“方法生命周期”的信息以及它与 AOP 的相关性?
    猜你喜欢
    • 2013-02-12
    • 1970-01-01
    • 2011-02-15
    • 2011-12-10
    • 2020-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多