【问题标题】:OSGi WeavingHook ExamplesOSGi WeavingHook 示例
【发布时间】:2013-03-11 10:28:07
【问题描述】:

有人有使用 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 在构造函数中是可以在文件系统上找到的 jar 或目录,而不是捆绑包。另外,我不确定如何通过回调GeneratedClassHandleracceptClass(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 兼容并且易于坚持使用 Wea​​vingHook.weave() 方法,我可以使用该方法修改原始类 byte[]... 是否有任何人实际这样做的示例?跨度>
  • 想到 ASM 或 BCEL。
  • @BJHargrave 很好,这两个都列在我的问题中(bcel 间接通过 aspectj)。在考虑了更多之后,我认为我需要aspectj的强大功能,但是通过aspectj源代码查看,它对osgi不友好。我看到的唯一可用的框架是春分方面。修改它以使用 OSGi 编织钩子而不是 equinox 扩展似乎比围绕 aspectj 编写自己的适配器要少。

标签: java osgi aop aspectj load-time-weaving


【解决方案1】:

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

【讨论】:

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

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

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

【讨论】:

    猜你喜欢
    • 2011-03-28
    • 2014-05-27
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 2013-12-07
    • 2011-06-02
    • 2010-11-24
    相关资源
    最近更新 更多