当切点在超类上但派生类覆盖时,如何避免两次命中切入点?

Posted

技术标签:

【中文标题】当切点在超类上但派生类覆盖时,如何避免两次命中切入点?【英文标题】:How to avoid hitting pointcut twice when the cut is on a superclass, but a derived class overrides? 【发布时间】:2012-08-31 00:10:50 【问题描述】:

很难给它起一个简洁的标题。

无论如何,假设我有一个父类:

    public class Shape 
        public Dimensions getDimensions() 
            // Does some generic stuff.
        
    

我有一个派生类,它覆盖了 getDimensions 方法:

    public class Circle extends Shape 
        public Dimensions getDimensions() 
            // Does some stuff.
            super.getDimensions();
        
    

当我在Shape.getDimensions 上创建带有切入点的切面时,在调用Circle.getDimensions 时会命中两次切入点:一次用于Circle.getDimensions,然后一次用于调用super.getDimensions

切入点如下所示:@Pointcut("execution(* Shape.getDimensions(..))")

我在建议中添加了一个 hack 来检查声明类型的名称(使用 JoinPoint.getSignature().getDeclaringType().getName()),但我觉得它很粗俗,感觉有点像 hack。我认为必须有更好的方法来做到这一点。

有吗?

如果格式不是很好,请见谅。第一次在这里问问题(我通常已经找到答案了)。

【问题讨论】:

【参考方案1】:

可能您的意思是您的切入点使用Shape+.getDimensions()(带有加号),否则它根本不会匹配Circle

无论如何,你可以像这样解决问题(我希望原生 AspectJ 语法对你来说没问题,我觉得它更清晰,更有表现力):

public aspect ShapeAspect 
    pointcut getDimensions() : execution(* Shape+.getDimensions());
    pointcut getDimensionsNoSuper() : getDimensions() && !cflowbelow(getDimensions());

    after() : getDimensionsNoSuper() 
        System.out.println(thisJoinPointStaticPart);
    

【讨论】:

效果很好,谢谢。我更习惯注释样式,但关键是 cflowbelow 调用。在试图弄清楚我是否可以将其浓缩成一个建议(无法弄清楚)的过程中,我发现了这个可爱的附录:eclipse.org/aspectj/doc/next/progguide/semantics-pointcuts.html 提前感谢您接受并支持我的回答。 ;-) 请做。 我显然需要 15 分才能这样做。我只有 11 个。相信我,我试过了! :( 其实execution也会匹配超类方法,不管有没有+ @Sean:这就是为什么切入点有另一个条件过滤掉超类方法的执行。你试过了吗?

以上是关于当切点在超类上但派生类覆盖时,如何避免两次命中切入点?的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate在超类中定义@Where注解

在超类中使用描述符以避免子类中的代码重复

是否可以在超类对象上调用子类的方法?

8- 类

Java:在超类方法签名中返回子类

模板方法