0

是否可以在加载时编织时使用 AspectJ 在编译的类文件上进行类型间声明?

举个例子:我编译了一些 Groovy 代码,想用 IDT 添加字段或方法。

4

1 回答 1

1

更新:

哦,天哪,您不需要反射来访问成员或执行方法。Eclipse 在编辑器中显示错误,但您可以忽略它们,代码编译并运行良好。所以这个方面真的更直接和简单:

public aspect LTWAspect {
    public static String Application.staticField = "value of static field";
    public String Application.normalField = "value of normal field";

    public void Application.myMethod() {
        System.out.println(normalField);
    }

    void around() : execution(void Application.main(..)) {
        System.out.println("around before");
        proceed();
        System.out.println("around after");
        System.out.println(Application.staticField);
        new Application().myMethod();
    }
}

原答案:

是的,但是你有一个先有后有的问题,即你不能只从你的 LTW 方面代码中引用新引入的字段而不进行反射。 (最后一句话不正确,请参阅上面的更新。)另外,为了使您的 LTW 方面编译,您需要在项目的构建路径上编织类,以便能够引用它们。例子:

Java 项目

public class Application {
    public static void main(String[] args) {
        System.out.println("main");
    }
}

AspectJ 项目

import org.aspectj.lang.SoftException;

public aspect LTWAspect {
    public static String Application.staticField = "value of static field";
    public String Application.normalField = "value of normal field";

    public void Application.myMethod() {
        try {
            System.out.println(Application.class.getDeclaredField("normalField").get(this));
        } catch (Exception e) {
            throw new SoftException(e);
        }
    }

    void around() : execution(void Application.main(..)) {
        System.out.println("around before");
        proceed();
        System.out.println("around after");
        try {
            System.out.println(Application.class.getDeclaredField("staticField").get(null));
            Application.class.getDeclaredMethod("myMethod", null).invoke(new Application());
        } catch (Exception e) {
            throw new SoftException(e);
        }
    }
}

因此,例如在 Eclipse 中,您需要将 Java 项目放在“Projects”下的 AspectJ 项目的构建路径上,因为只有这样它才能看到Application您要在其上声明成员的 Java 类。编译后,您只需启动 Java 项目并在方面项目上执行 LTW(不要忘记aop-ajc.xml引用LTWAspect)。

在上面的示例中,我声明了一个静态成员、一个非静态(“普通”)成员和一个非静态方法。我的建议通过反射打印静态成员并调用非静态方法。然后,非静态方法再次通过反射打印非静态成员。这不是很好,但它可以工作并证明 ITD 与 LTW 结合是可能的。可能有更优雅的方式,但如果是这样,我不知道。(更新:有一种更优雅的方法:只需忽略 Eclipse IDE 标记的错误,见上文。)

程序输出

around before
main
around after
value of static field
value of normal field
于 2013-05-03T09:33:14.220 回答