【问题标题】:Is it possible to exclude interface classes from AspectJ weaving是否可以从 AspectJ 编织中排除接口类
【发布时间】:2013-10-24 18:40:18
【问题描述】:

场景:

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

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,而不是Object,但无济于事。

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

很确定没关系,但我正在使用 javaagent 的加载时编织。

【问题讨论】:

    标签: java interface aspectj load-time-weaving


    【解决方案1】:

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

    解决方案如下:

    不包括 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());
        }
    }
    

    顺便说一句,即使您不排除枚举,枚举也不会实现该接口。但是你会得到编译器错误“can't use declare parents to make enum type com.mycompany.data.Gender implementation an interface”。

    验证ITD效果的驱动应用:

    应用程序遍历所有相关的类、枚举、接口并检查它们是否确实实现了Secure 接口。由于!is(InterfaceType) && !is(EnumType) 子句,我们希望枚举Gender 和接口Animal 可以免于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
    

    特别感谢 AspectJ 维护者 Andy Clement,他将我指向 AspectJ 1.6.9 release notes(搜索“Type category type patterns”),因为该功能在其他方面没有记录尽管它是 AspectJ 语言的官方部分。

    【讨论】:

    • 谢谢!这似乎正是我想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多