当前位置: 首页 > 知识库问答 >
问题:

类列表的所有方法上的AspectJ切入点

戚育
2023-03-14

我想从类列表(可能属于不同的包)中记录所有方法的条目。注意,这些方法应该只属于指定的类。

我尝试了以下方法,但这些都不起作用

(1) 在这里使用if()切入点,我得到一个错误

"incompatible number of arguments to pointcut, expected 1 found 0"

@Pointcut("execution(*.*(..)) && if()")
public static boolean mycut(JoinPoint jp) {
     boolean matches = ... ;//Test using jp if the declaring class belongs to the list
     return matches;
}

(2) 使用切入点和aop的组合。xml在这里我得到一个错误

java.lang.NoSuchMethodError:
com.mypackage.TraceAspect.aspectOf()Lcom/df/jc/aspect/TraceAspect;

//in com.mypackage.TraceAspect aspect class
@Pointcut("execution(*.*(..)) && !within(com.mypackage.TraceAspect)")
public void mycut(){
}

//in aop.xml
<weaver>
    <include within="package1.Class1">
    <include within="package2.Class2">
    <include within="package3.Class3">
</weaver>

这里出了什么问题?

当然可以通过在切入点中单独指定每个类来实现,但这对于数百个类来说是不可扩展的。理想情况下,如果可以从外部文本文件中提取类列表(便于配置),那就太好了

共有1个答案

陈君之
2023-03-14

至于你最后的评论:除了糟糕的设计,我并没有阻止你做任何事情,我只是想鼓励你做正确的事情:重构,不要让自己的生活变得比必要的更艰难。您甚至不知道AspectJ语法的基础知识,但您已经想用大量的类实现一个过于复杂的场景,这是一个维护噩梦。我试图通过激励你不要做出短视的决定来帮助你。相信我,我多年来一直在使用AspectJ,在你所说的带有大量遗留代码的现实项目中。即使是最便宜的重构,也要比智能重构昂贵得多——不算太多,但根据童子军规则,这已经足够了:让营地比你发现的更干净。相信我,这是值得的。

无论如何,谈谈你的代码片段:

  • 执行(*.*(...))在语法上是错误的,因为您没有为要匹配的方法指定返回类型(或占位符)。您想使用执行(**.*(...))或简写版本执行(**(...))
  • 错误“与切入点不兼容的参数数,预期1找到0”不是来自您的切入点,而是来自您甚至没有费心发布的建议。您必须编写类似@前("myCut()")的内容,但正确的是@前("myCut(jp)")

话虽如此,这里有一个简单、完全自包含且可编译的示例:

驱动程序应用:

package de.scrum_master.app;

public class Application {
    public static void main(String[] args) {
        System.out.println(multiply(3, add(4, 5)));
    }

    public static int multiply(int i, int j) { return i * j; }
    public static int add(int i, int j) { return i + j; }
}

方面:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class TraceAspect {
    @Pointcut("execution(* *(..)) && if()")
    public static boolean hasMatchingSignature(JoinPoint thisJoinPoint) {
        return !thisJoinPoint.getSignature().getName().equals("main");
    }

    @Before("hasMatchingSignature(thisJoinPoint)")
    public void myAdvice(JoinPoint thisJoinPoint) {
        System.out.println(thisJoinPoint);
    }
}

样品输出:

execution(int de.scrum_master.app.Application.add(int, int))
execution(int de.scrum_master.app.Application.multiply(int, int))
27

如果您的If()切入点只返回true,那么输出也将显示main的执行。

 类似资料:
  • 问题内容: 我有针对特定软件包的此工作代码,但我想针对所有 controllers , service 和 dao 软件包进行配置 com.abc.xyz.content.controller com.abc.xyz.content.service com.abc.xyz.content.dao com.abc.xyz.category.controller com.abc.xyz.categor

  • 问题内容: 我想用指定的注释(例如@Monitor)监视所有类的所有公共方法(注意:注释在类级别)。可能的切入点是什么?注意:我正在使用@AspectJ样式的Spring AOP。 问题答案: 你应该将类​​型切入点与方法切入点结合使用。 这些切入点将在标记为@Monitor的类中查找所有公共方法: 为结合了前两者的最后一个切入点提供建议,你就完成了!

  • 我正在使用Spring的AspectJ和CGLIB代理。我有一个定义如下的方面,我希望它在具体的类上为公共方法提供建议,这些类是用批注“validatormethod”批注的:

  • 使用加载时间编织,纯AspectJ。 我们有2个注释和,以及一些带注释的方法。 现在我正在为具有多个注释的定义自己的围绕方面: 这行不通。然而,捕获方法myMethod2可以很好地用于单个注释: 我只想捕获签名中同时存在时间和计数注释的方法,并且我想使用注释值。有人知道如何做到这一点吗?

  • add:如果我将方法存根添加到Fragment2中,就可以开始使用next annotation,但这是一个非常难看的解决方案 解决方案:多亏了@Kriegaex,我找到了解决方案:

  • 服务实现 但是,如果我将注释移动到公共接口方法实现,我的方面就会被触发。我应该如何定义我的切入点或配置我的方面来使我的原始用例工作?