Java OSGi编织钩示例

Java OSGi编织钩示例,java,osgi,aop,aspectj,load-time-weaving,Java,Osgi,Aop,Aspectj,Load Time Weaving,有人有使用OSGi4.3+编织钩子服务的例子吗?那么AspectJ、ASM和JavaAssist呢?有人真的在用OSGi编织钩吗 OSGi Core 5.0.0第56.2节中的示例只是省略了实际的编织,并说“最终的编织留给读者作为练习” 我的目标是: 创建可以放置在字段(基本体或对象)上的批注(@MyAnnotation) 创建org.osgi.framework.hooks.weaving.WeavingHook以使用该注释编织类 在对带有该注释的字段进行任何修改时,使用加载时编织到切入点 已

有人有使用OSGi4.3+编织钩子服务的例子吗?那么AspectJ、ASM和JavaAssist呢?有人真的在用OSGi编织钩吗

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

我的目标是:

  • 创建可以放置在字段(基本体或对象)上的批注(@MyAnnotation)
  • 创建org.osgi.framework.hooks.weaving.WeavingHook以使用该注释编织类
  • 在对带有该注释的字段进行任何修改时,使用加载时编织到切入点
  • 已修改字段的fire EventAdmin事件
  • 动态更新从WeavingHook到EventAdmin捆绑包的捆绑包连接 我的问题主要是3

    我目前正尝试使用AspectJ进行编织,但在将方面库放入方面库时遇到了问题,因为它希望构造函数中的java.net.URL[]aspectURLs是JAR或它可以在文件系统上找到的目录,而不是捆绑包。另外,我不知道如何处理weaver通过回调函数的acceptClass(String name,bytes[])方法生成的任何新类

    也许编织适配器不是我开始编织的合适地方?或者我不应该使用AspectJ

    MyAnnotation.java

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
    }
    
    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
        }
    }
    
    public class MyTestClass {
        @MyAnnotation
        private int myField;
    
        public void doSomething() {
          //do stuff with myField
        }
    }
    
    MyWeavingHook.java

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
    }
    
    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
        }
    }
    
    public class MyTestClass {
        @MyAnnotation
        private int myField;
    
        public void doSomething() {
          //do stuff with myField
        }
    }
    
    MyAspect.aj

    privileged aspect MyAspect {
        after() : set(* *) && @annotation(MyAnnotation) {
          //send EventAdmin event
        }
    }
    
    MyTestClass.java

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
    }
    
    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
        }
    }
    
    public class MyTestClass {
        @MyAnnotation
        private int myField;
    
        public void doSomething() {
          //do stuff with myField
        }
    }
    
    我可以使用SpringAOP,但我希望它适用于任何包,而不仅仅是通过Spring或Blueprint实例化的bean。另外,Equinox编织似乎还没有使用OSGi编织钩子规范,我不想被束缚在Equinox上。如果其他东西工作得更好,我可以放弃AspectJ

    提及类似问题:

    更新:


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

    查看ApacheAries的代理模块。它直接使用ASM库修改字节码,使其级别更低

    WeavingAdapter希望您的WeavingClassLoader是从URLClassLoader派生的,因此两个可用的构造函数最终基本上做相同的事情。签出以查看如何利用bundlewing来访问类路径URL。您可以将AspectJ运行时包添加到wovenClass.getDynamic'Imports()中,以避免直接引用AspectJ。BundleWiring也是为WeavingAdapter提供AspectJ URL的一种方式


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

    对于OSGi编织钩子,您会得到需要修改的类的字节[]。您不能尝试加载变异字节[]。这将由OSGi框架在调用所有编织钩子后完成。@bhargrave是的,规范是这么说的。问题是,哪些框架或库与OSGi兼容,并且很容易在WeavingHook.weave()方法中使用,我可以用它修改原始的类byte[]。。。有人真的这样做过吗?我想到了ASM或BCEL。@bhargrave好吧,这两个都列在我的问题中(BCEL通过aspectj间接列出)。在详细考虑了这一点之后,我认为我需要aspectj的强大功能,但是通过aspectj源代码来看,它并不支持osgi。我看到的唯一可用的框架是equinox方面。修改它以使用OSGi编织钩子而不是equinox扩展似乎比围绕aspectj编写自己的适配器工作量要少。您的答案是唯一的,也是合理的答案。最终的结果是我使用了Equinox Aspects并将其安装到Karaf中。是3个捆绑包、一个库和一个系统属性。我将使用它,直到他们将它更新为我们的OSGi编织,或者我编写自己的OSGi编织钩子来使用类似于Equinox方面的AspectJ代码。我不喜欢让Equinox方面工作所需的编织指标,因为它在要编织的捆绑包中引入了一个require bundle/reexport或AspectJ RT上的导入包。此依赖项应在捆绑包之外动态添加和通知。