【发布时间】:2013-03-11 10:28:07
【问题描述】:
有人有使用 OSGi 4.3+ Weaving Hook Service 的例子吗? AspectJ、ASM、JavaAssist 怎么样?有人真的在使用 OSGi WeavingHooks 吗?
OSGi Core 5.0.0 第 56.2 节中的示例简单地省略了实际的编织,并说“最终的编织留给读者作为练习”。
我的目标是:
- 创建一个注释 (@MyAnnotation),我可以将它放在字段(基元或对象)上。
- 创建一个 org.osgi.framework.hooks.weaving.WeavingHook 以使用该注释编织类
- 使用加载时编织来切入带有该注释的字段的任何修改
- 触发字段被修改的 EventAdmin 事件。
- 动态更新从 WeavingHook 绑定到 EventAdmin 绑定的绑定。
我的问题主要在于#3。
我目前正在尝试使用 AspectJ WeavingAdaptor 进行编织,但我在将方面库放入其中时遇到问题,因为它需要 java.net.URL[] aspectURLs 在构造函数中是可以在文件系统上找到的 jar 或目录,而不是捆绑包。另外,我不确定如何通过回调GeneratedClassHandler 的 acceptClass(String name, bytes[]) 方法来处理编织器生成的任何新类。
也许 WeavingAdaptor 不是开始编织的正确位置?或者我不应该使用 AspectJ?
MyAnnotation.java
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
MyWeavingHook.java
public class MyWeavingHook implements WeavingHook {
public class MyWeavingClassloader implements WeavingClassLoader {
private Bundle b;
public MyWeavingClassLoader(Bundle b) {
this.b = b;
}
void acceptClass(java.lang.String name, byte[] bytes) {
//no way to get this back into the woven classes bundle classloader?
}
URL[] getAspectURLs() {
//how do I get a handle to my aspect library that AspectJ can understand?
}
}
public void weave(WovenClass myclass) {
Bundle b = Framework.getBundle(MyWeavingHook.class);
WeavingClassLoader wc = new WeavingClassLoader(b);
WeavingAdaptor w = new WeavingAdaptor(wc);
if (shouldWeave(myclass))
myclass.setBytes(w.weave(myClass.getBytes()));
//should catch exceptions
}
private boolean shouldWeave(WovenClass myclass) {
//not sure of the best logic to pick which classes to weave yet
}
}
MyAspect.aj
privileged aspect MyAspect {
after() : set(* *) && @annotation(MyAnnotation) {
//send EventAdmin event
}
}
MyTestClass.java
public class MyTestClass {
@MyAnnotation
private int myField;
public void doSomething() {
//do stuff with myField
}
}
我可以使用 Spring AOP,但我希望它适用于任何包,而不仅仅是通过 Spring 或 Blueprint 实例化的 bean。此外,Equinox Weaving 似乎还没有使用 OSGi 编织钩子规范,我不想被 Equinox 束缚。如果其他方法效果更好,我可以放弃 AspectJ。
参考类似问题:Is it possible to do bytecode manipulation when using OSGi?
更新:
最终结果是我刚刚使用 Equinox Aspects 并将其安装到 Karaf 中。是 3 个捆绑包、一个库和一个系统属性。我将一直使用它,直到他们将其更新为我们的 OSGi 编织,或者我编写自己的 OSGi 编织钩子以使用类似于 Equinox Aspects 的 AspectJ 代码。我不喜欢让 Equinox Aspects 工作所需的编织指标,因为它在要编织的包中的 AspectJ RT 上引入了 require-bundle/reexport 或 import-package。此依赖项应在捆绑包之外动态添加和建议。
【问题讨论】:
-
对于 OSGi 编织钩子,您会得到需要修改的类的字节[]。您不得尝试加载变异的 byte[]。这将在调用所有编织钩子后由 OSGi 框架完成。
-
@BJHargrave 是的,这就是规范所说的。问题是,哪些框架或库与 OSGi 兼容并且易于坚持使用 WeavingHook.weave() 方法,我可以使用该方法修改原始类 byte[]... 是否有任何人实际这样做的示例?跨度>
-
想到 ASM 或 BCEL。
-
@BJHargrave 很好,这两个都列在我的问题中(bcel 间接通过 aspectj)。在考虑了更多之后,我认为我需要aspectj的强大功能,但是通过aspectj源代码查看,它对osgi不友好。我看到的唯一可用的框架是春分方面。修改它以使用 OSGi 编织钩子而不是 equinox 扩展似乎比围绕 aspectj 编写自己的适配器要少。
标签: java osgi aop aspectj load-time-weaving