• OSGI依赖问题处理


    用osgi实现java的模块化和热插拔时要考虑好两个问题,不同bundle间如何通信?依赖怎么处理?

    OSGi的一个标准就是各个bundle之间是相互隔离的,每个bundle都有自己的classloader,并且不同的版本之间都是相互隔离的,这样就使bundle从物理上进行了隔离,那么OSGi 的bundle之间是怎么进行通信的呢?

    下面我们将要介绍3中方法。

    Bundles之间通信的方法

    方法 描述
    1.Export-Package 根据OSGi规范,每个工程可以通过声明Exprot-Package对外提供访问此工程中的类和接口,可以先把bundle导出,再导入到需要调用的bundle中
    2.OSGi服务 通过将要对外提供功能声明为OSGi的服务实现面向接口、面向服务式的设计;
    3.Event 基于OSGi的Event服务也是实现模块交互的一种可选方法,模块对外发布事件,订阅了此事件的模块就会相应地接收到消息,从而做出反应,以达到交互的目的。

    OSGi bundle之间互相通信的方法

    在JAVA程序中,用到外部包中的类几乎是必然的事情,在OSGI和MAVEN环境下,引用外部包的方法总结如下:

    1.java.开头的包,是JDK提供了,代码中直接import。

    2.org.osgi开头的(包括core、compendium等),是osgi规范提供的,已经包含在osgi框架(Felix)中,开发时需要导入,但是发布程序中不需要包含,由Felix提供,实现方法是添加scope为provided的maven依赖,如:

           <dependency>

                <groupId>org.osgi</groupId>

                <artifactId>org.osgi.core</artifactId>

                <version>4.3.0</version>

                <scope>provided</scope>

            </dependency>

    另外如果使用AS容器,而不是osgi嵌入http service,那么jee相关的包如servlet-api也是provided。

    3.第三方jar包,可能有多个bundle共享的,直接osgi化,然后作为独立bundle安装到Felix中,例如commons-io-1.4.jar,Felix的WebConsole子项目依赖它,我们的很多bundle也可能用到它,开发时在maven中加入

    <dependency>

        <groupId>commons-io</groupId>

        <artifactId>commons-io</artifactId>

        <version>1.4</version>

    </dependency>

    部署时从maven库中找到这个jar包,然后直接放到Felix的bundle目录,启动Felix,就可以看到这个jar包作为一个独立bundle已经启动,其他bundle就可以通过直接Import-Package的方式来引用这些包。的之所以能够这么做是因为这个jar已经osgi化了,查看jar包中的META-INF/MENIFEST.MF文件,只要其中有Bundle-SymbolicName: org.apache.commons.io等一系列Bundle-*的属性值,并且有Export-Package导出内部的包就可以确定。现在大部分从maven库中获得的比较新的jar包,基本上都已经支持OSGI了。如果一个jar包确实不包含OSGI信息,也可以通过手动编辑它的MENIFEST.MF文件增加OSGI信息,来实现这个jar包独立作为bundle运行。例如json-20090211.jar,直接编辑它的MENIFEST.MF如下:

    Manifest-Version: 1.0
    Created-By: 1.6.0_07 (Sun Microsystems Inc.)
    Export-Package: org.json
    Bundle-Name: JSON
    Bundle-Version: 20090211
    Bundle-SymbolicName: org.json
    确保jar包的格式(如果解压编辑,要重新打包,最好用解压软件直接打开编辑自动打包),然后就直接在Felix中运行了。

    4.第三方的jar包,不考虑多个bundle共享,只确保一个bundle的独立依赖,可以把这些依赖的jar嵌入到开发的bundle中发布。如在开发com.ailk.common.log4j时,查看log4j的pom发现它依赖多个其他jar包(不同版本log4j依赖的jar包不一样,这里是1.2.15版本的情况)

            <dependency> 

                <groupId>javax.mail</groupId> 

                <artifactId>mail</artifactId> 

                <version>1.4</version> 

            </dependency> 

            <dependency> 

                <groupId>javax.jms</groupId> 

                <artifactId>jms</artifactId> 

                <version>1.1</version> 

            </dependency> 

            <dependency> 

                <groupId>com.sun.jdmk</groupId> 

                <artifactId>jmxtools</artifactId> 

                <version>1.2.1</version> 

            </dependency> 

            <dependency> 

                <groupId>com.sun.jmx</groupId> 

                <artifactId>jmxri</artifactId> 

                <version>1.2.1</version> 

            </dependency> 

    maven中加入这些就可以在开发时引用了,但是发布到Felix框架时,我们要把这些jar包一起提供才行,方法是把这些jar包嵌入到我们的bundle中,使用maven-bundle-plugin,增加instructions配置<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>,这样maven在打包是就可以自动把这些依赖的jar包嵌入。要注意这些依赖的scope和Embed-Dependency的表述方式的匹配,具体Embed-Dependency可能的写法请参见maven-bundle-plugin在线文档。

    这种方式引用外部包,好处是自带依赖,操作简单,不像方法3中那样,如果依赖jar包更新要受到影响,并且要注意多个bundle共享依赖是否有冲突。坏处是所有依赖jar包都要一起打包到bundle中,显得非常臃肿。

    5.自己开发的bundle之间,互相引用其他bundle的包,被引用者注意要Export-Package,并打包部署到maven库,其他引用的bundle在开发阶段通过maven依赖直接引用,在部署时确保几个管理的bundle同时都在Felix中并且resolved。

    6.嵌入包瘦身,针对上面第四点,在嵌入第三方包到bundle时,如果完全按照pom中指定的依赖全部打包进bundle,bundle体积会比较大,但是这些jar包是否全部都是必须的呢?不一定。例如log4j的pom指定依赖javax.mail的mail.jar,但是如果不使用mail方式的appender,这个jar基本上是用不到的。同样mybatis的pom中也包含了5种log实现作为依赖,包括log4,slf4j,common-logging等,但是实际上这个日志功能并不是必须全部具备,嵌入全部这些log实现的jar就显得多余。但是如果在pom中不配置这些jar包的依赖,开发编译阶段没有问题,但是bundle在resolve的过程会包缺少需要的package。解决方法是在pom中仍然加入这些Jar包的依赖,但是增加一个<optional>true</optional>的属性,同时修改打包instructions为<Embed-Dependency>*;scope=compile|runtime;optional=!true</Embed-Dependency>。经验证,这做是可以的,log4j的bundle不再包含mail,jms,jmxtools,jmxri几个jar包后,体积减少了一半以上,功能不受影响。

    http://blog.csdn.net/rosen_luo/article/details/47398391

  • 相关阅读:
    关于微软 2012 暑期实习题第 5 题
    ZOJ 1608. Two Circles and a Rectangle
    在技术社区以外的博文中插入代码(把代码转换到 Html 文本)
    ZOJ 2240. Run Length Encoding
    C++中“引用”的底层实现
    采用路径模型实现遍历二叉树的方法
    ZOJ 简单题集合(四)
    ZOJ 3603. Draw Something Cheat
    关于类的虚函数表
    ZOJ 3499. Median
  • 原文地址:https://www.cnblogs.com/doit8791/p/7745862.html
Copyright © 2020-2023  润新知