rob*_*blg 5 java aspectj interface 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 ...
Run Code Online (Sandbox Code Playgroud)
目标:让所有类都实现新的接口和新的方法。
问题:我可以成功地将接口编织到类中,并排除枚举,但是我无法弄清楚如何也不能将新接口添加到包中的接口上。
我的方面目前看起来像:
public aspect SecureAspect {
declare parents: com.mycompany.data.* && !java.lang.Enum+ implements Secure;
// add method from secure interface to everything implementing Secure
}
Run Code Online (Sandbox Code Playgroud)
它匹配Dog,Cat和Animal在我的例子。
我以前尝试过:
declare parents: com.mycompany.data.* && java.lang.Object+ && !java.lang.Enum+ implements Secure;
Run Code Online (Sandbox Code Playgroud)
因为Animal.class.getSuperclass() == null,与Object相反,但无济于事。
我知道我可以通过将接口移出软件包来解决此问题(如果很不可能,我很乐意这样做),但是我很好奇是否有一种方法可以像我以前那样排除接口枚举。
可以肯定,这没关系,但是我正在使用Javaagent的加载时编织。
这个问题很老了,但我发现它很有趣并做了一些研究。
解决方案如下所示:
从 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());
}
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,即使您不排除枚举,枚举也不会实现该接口。但随后您会收到编译器错误“无法使用声明父对象使枚举类型 com.mycompany.data.Gender 实现接口”。
驱动程序应用验证ITD效果:
应用程序迭代所有相关的类、枚举、接口并检查它们是否确实实现了该Secure接口。由于该条款,我们预计枚举Gender和接口Animal将免受 ITD 的影响!is(InterfaceType) && !is(EnumType)。如果确实实现了该接口,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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
控制台输出:
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
Run Code Online (Sandbox Code Playgroud)
特别感谢AspectJ 维护者Andy Clement,他向我指出了AspectJ 1.6.9 发行说明(搜索“类型类别类型模式”),因为该功能虽然是 AspectJ 语言的官方部分,但并未记录在案。
| 归档时间: |
|
| 查看次数: |
1019 次 |
| 最近记录: |