12

有人有使用 OSGi 4.3+ Weaving Hook Service 的例子吗?AspectJ、ASM、JavaAssist 怎么样?有人真的在使用 OSGi WeavingHooks 吗?

OSGi Core 5.0.0 第 56.2 节中的示例简单地省略了实际的编织,并说“最终的编织留给读者作为练习”。

我的目标是:

  1. 创建一个可以放在字段(基元或对象)上的注释(@MyAnnotation)。
  2. 创建一个 org.osgi.framework.hooks.weaving.WeavingHook 以使用该注释编织类
  3. 使用加载时编织来切入具有该注释的字段的任何修改
  4. 触发字段被修改的 EventAdmin 事件。
  5. 动态更新来自 WeavingHook 的包连接以连接到 EventAdmin 包。

我的问题主要是#3。

我目前正在尝试使用 AspectJ WeavingAdaptor进行编织,但是在将方面库放入其中时遇到问题,因为它期望构造函数中的java.net.URL[] aspectURLs是罐子或目录它可以在文件系统上找到,而不是捆绑包。另外,我不确定如何通过回调到 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
    }
}

我的方面.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。

参考一个类似的问题:使用 OSGi 时是否可以进行字节码操作?

更新:

最终结果是我刚刚使用 Equinox Aspects 并将其安装到 Karaf 中。是 3 个捆绑包、一个库和一个系统属性。我会一直使用它,直到他们将它更新为我们的 OSGi 编织,或者我编写自己的 OSGi 编织钩子以使用类似于 Equinox Aspects 的 AspectJ 代码。我不喜欢让 Equinox Aspects 工作所需的编织指标,因为它在要编织的包中的 AspectJ RT 上引入了 require-bundle/reexport 或 import-package。应该在捆绑包之外动态添加和建议此依赖项。

4

2 回答 2

2

看看Apache Aries 的 Proxy 模块中的ProxyWeavingHook。它直接使用 ASM 库来修改字节码,使其更底层。

于 2013-04-08T08:54:55.927 回答
0

WeavingAdaptor 期望您的 WeavingClassLoader 从 URLClassLoader 派生,因此两个可用的构造函数最终基本上做同样的事情。查看http://www.slideshare.net/mfrancis/bytecode-weaving以了解如何利用BundleWiring来访问类路径 URL。您可以将 AspectJ 运行时包添加到 wovenClass.getDynamic'Imports() 以避免直接 AspectJ 引用。BundleWiring 也是为 WeavingAdaptor 提供 AspectJ url 的方式。

我认为没有办法支持来自 acceptClass 的新类,因为编织钩子指出动态导入只能在编织方法内部使用。

于 2013-05-24T06:52:39.477 回答