场景:
我将类、接口(interface)和枚举的源文件混合在一个包中,如下所示:
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 ...
目标:让所有类实现一个新接口(interface)和一个新方法。
问题:我可以成功地将接口(interface)编织到类中,并排除枚举,但我不知道如何防止新接口(interface)被添加到类中的接口(interface)上包装也是如此。
我的方面目前看起来像:
public aspect SecureAspect {
declare parents: com.mycompany.data.* && !java.lang.Enum+ implements Secure;
// add method from secure interface to everything implementing Secure
}
在我的示例中匹配 Dog
、Cat
和 Animal
。
我之前尝试过:
declare parents: com.mycompany.data.* && java.lang.Object+ && !java.lang.Enum+ implements Secure;
因为 Animal.class.getSuperclass() == null
,与 Object 相反,但无济于事。
我知道我可以通过将接口(interface)移出包来解决这个问题(如果事实证明这是不可能的,我很乐意这样做),但我很好奇是否有办法排除接口(interface),比如我用枚举做了。
很确定这无关紧要,但我正在使用 javaagent 的加载时编织。
最佳答案
这个问题很老了,但我发现它很有趣并做了一些研究。
解决方案如下所示:
从 ITD 中排除枚举和接口(interface)的方面:
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());
}
}
顺便说一句,枚举无论如何都不会实现接口(interface),即使你不排除它们。但是随后您会收到编译器错误“无法使用声明父项来使枚举类型 com.mycompany.data.Gender 实现接口(interface)”。
验证ITD效果的司机申请:
应用程序遍历所有相关类、枚举、接口(interface)并检查它们是否确实实现了Secure
接口(interface)。由于 !is(InterfaceType) && !is(EnumType)
子句,我们希望枚举 Gender
和接口(interface) Animal
免于 ITD。如果确实实现了接口(interface),将通过反射调用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 语言的官方部分。
关于java - 是否可以从 AspectJ 编织中排除接口(interface)类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19573968/