是否可以从AspectJ编织中排除接口类

时间:2013-10-24 18:40:18

标签: java interface aspectj load-time-weaving

情景:

我将类,接口和枚举的源文件混合在一个包中,如下所示:

package com.mycompany.data;
class Dog {
    // implementation
}

package com.mycompany.data;
class Cat {
    // implementation
}

package com.mycompany.data;
enum Gender {
    // gender options
}

package com.mycompany.data;
interface Animal {
    // methods
}

// ... plus a lot more concrete classes and a few more interfaces ...

目标:让所有类实现新界面和新方法。

问题:我可以成功地将接口编织到类中,并排除枚举,但我无法弄清楚如何防止新接口被添加到接口中包装也是如此。

我的方面目前看起来像:

public aspect SecureAspect {
    declare parents: com.mycompany.data.* && !java.lang.Enum+ implements Secure;

    // add method from secure interface to everything implementing Secure
}

我的示例中匹配DogCatAnimal

我之前尝试过:

declare parents: com.mycompany.data.* && java.lang.Object+ && !java.lang.Enum+ implements Secure;

因为Animal.class.getSuperclass() == null而不是对象,但无济于事。

我知道我可以通过将接口从包中移出来解决这个问题(如果事实证明这是不可能的,我很乐意这样做),但我很好奇是否有办法排除类似的接口我做了Enums。

非常确定无所谓,但我正在使用javaagent进行加载时编织。

1 个答案:

答案 0 :(得分:3)

这个问题已经过时了,但我发现它很有趣,并做了一些研究。

解决方案如下所示:

从ITD排除枚举和界面的方面:

package com.mycompany.aspect;

import com.mycompany.data.Secure;

public aspect SecureAspect {
    declare parents :
        !is(InterfaceType) && !is(EnumType) && com.mycompany.data.*
        implements Secure;

    public void Secure.doSomething() {
        System.out.println("I am a secure " + this.getClass().getSimpleName());
    }
}
顺便说一下,即使你不排除它们,enums仍然不会实现该接口。但是你会得到编译器错误"不能使用声明父类来生成枚举类型com.mycompany.data.Gender实现一个接口"。

验证ITD效果的驱动程序应用程序:

应用程序迭代所有相关的类,枚举,接口并检查它们是否确实实现了Secure接口。由于Gender子句,我们希望枚举Animal和接口!is(InterfaceType) && !is(EnumType)免于ITD。如果确实实现了接口,则会通过反射调用doSomething方法,以便仔细检查ITD效果。

package com.mycompany.data;

public class Application {
    public static void main(String[] args) throws Exception {
        for (Class<?> clazz : new Class[] { Application.class, Cat.class, Dog.class, Gender.class, Animal.class }) {
            String implementsYesNo = " does not implement";
            for (Class<?> iface : clazz.getInterfaces()) {
                if (iface == Secure.class) {
                    implementsYesNo = " implements";
                    Object instance = clazz.newInstance();
                    clazz.getMethod("doSomething").invoke(instance);
                    break;
                }
            }
            System.out.println(clazz.getSimpleName() + implementsYesNo + " interface Secure\n");
        }
    }
}

控制台输出:

I am a secure Application
Application implements interface Secure

I am a secure Cat
Cat implements interface Secure

I am a secure Dog
Dog implements interface Secure

Gender does not implement interface Secure

Animal does not implement interface Secure

特别感谢 Andy Clement ,AspectJ维护者,他向我指出AspectJ 1.6.9 release notes(搜索&#34;类型类别类型模式&#34; )因为该功能在其他方面没有记录,即使它是AspectJ语言的官方部分。