当前位置:七道奇文章资讯编程技术Java编程
日期:2011-03-22 16:15:00  来源:本站整理

模块化Java:动态模块化[Java编程]

赞助商链接



  本文“模块化Java:动态模块化[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:

在前一篇文章《模块化Java:静态模块化》中,我们谈论了若何构建Java模 块并将其作为一个单独的JAR举行布置.文中的例子给出了一个client和一个 server bundle(二者在同一个VM中),client通过工厂办法找到server.在该 例子中,工厂实例化了一个已知类,当然也可以利用反射来获得一个服务实现; Spring就是大量应用这种技术把spring对象绑定在一同的.

在我们谈论动态服务之前,有必要回想一下类途径,因为尺度Java代码和模 块化Java代码的辨别之一就是依靠在运行时是若何绑定的.在此之后,我们还将 简单谈论一下类的垃圾回收;假如你对此已非常熟习,则可以跳过这部份内容.

Bundle ClassPath

关于一个普通Java程序,只有一个classpath——启动利用程序所利用的那个 .该途径普通是在号令行顶用-classpath选项指定的,大概通 过CLASSPATH 环 境变量来设定.Java类装载器在运行时解析类的时刻会扫描此途径,无论这一过 程是静态地(已编译进代码)还是动态地(利用反射及 class.forName()).然 而,在运行时也可以利用多个类加载器;像Jetty和Tomcat这样的Web利用引擎都 是利用多个类加载器,以便支持利用热布置.

在OSGi中,每个bundle都有其自己的类加载器.需求被其他bundle拜候的类 则被委派(delegated)给这些其他bundle的类装载器.因此,固然在传统利用 中,来自logging类库、client和server JAR中的类都是由同一个类加载器加载 的,但在OSGi模块系统中,他们都是由自己的类加载器加载的.

后果是,一个VM中有大概有多个类加载器,此中大概存在名字相同的差别 Class的对象.也就是说,在同一个VM中,一个叫做 com.infoq.example.App的 类,其差别版本可以由com.infoq.example bundle的第1版和第2版同时输出. Client bundle版本1利用该类的第1版,而client版本2利用该类的第2版.这在 模块化系统中相当广泛;在同一个VM中,有些代码大概需求装载一个类库的老版 本,同时更新点的代码(在另一个bundle中)却需求该类库的新版本.好在OSGi 为你管理起这种依靠传送,确保不再呈现不兼容类引发的问题.

类的垃圾回收

每个类都有一个对其类装载器的引用.因此假如想要从差别的bundle拜候这 些类,不但要有对该类实例的引用,并且还要有对该类的类装载器的引用.当一 个bundle持有另一个bundle的类时,它也会将该bundle固定在内存中.在前篇文 章的例子中,client被固定到该server上.

在静态世界里,无论你能否把自己的类固定到其他类(或类库)都无所谓; 因为不会有什么改变.但是,在动态世界里,在运行时将类库或工具替换成新版 本就有大概了.这听起来大概有点复杂,但是在可热布置利用的Web利用引擎早 期就呈现了(如Tomcat,最早公布于1999年).每个Web利用程序都绑定到 Servlet API的某个版本上,当其终止时,装载该Web利用的类加载器也就废弃掉 了.当Web利用重新被布置时,又成立了一个新的类加载器,新版类就由其装载 .只要servlet引擎没有保持对老版利用的引用,这些类就像其他Java对象一样 被垃圾回收器回收了.

并非全部的类库都能意识到Java代码中大概存在类泄露的问题,就像是内 存泄露.一个典型的例子就是Log4J的addAppender()调用,一旦其履行了,将会 把你的类绑定在Log4J bundle的生命周期上.即便你的bundle终止了,Log4J仍 将维对appender的引用,并持续发送日记事件(除非该bundle在终止时恰本地调 用了removeAppender()办法).

查找和绑定

为了成为动态,我们需求有一个能查找服务的机制,而不是长期持有他们( 免得bundle终止).这是通过利用简单Java接口和POJO来实现的,也就是大家所 熟知的services(注意他们与WS-DeathStar或其他任何XML底层架构都没有关系 ;他们就是普通Java对象——Plain Old Java Objects).

典型工厂实现方法是利用从properties文件中获得的某种情势的类名,然后 用Class.forName()来实例化呼应的类,OSGi则差别,它 保护了一个‘服务注册 器’,其实这是一个包含了类名和服务的映射列表.这样,OSGi系统便可以利用 context.getService(getServiceReference("java.sql.Driver")),而不是 class.forName("com.example.JDBCDriver")来获得一个JDBC驱动器.这就把 client代码约束出来了,它不需知道任何特定客户端实现;相反,它可以在运行 时绑定任何可用驱动程序.移植到差别的数据库服务器也就非常简单了,只需停 止一个模块并启动一个新模块;client乃至不需求重新启动,也不需求改变任何 配置.

这样做是因为client只需知道其所需的服务的API(基本上都是接口,固然 OSGi标准答应利用其他类).在上述情形中,接口名是 java.sql.Driver;返回 的接口实例是具体的数据库实现(没必要理解是哪些类,编码在那边).此外,如 果服务不可用(数据库不存在,或数据库暂时停掉了),那么这个办法会返回 null以阐明该服务不可用.

为了完好动态,返回后果不该被缓存.换句话说,每当需求服务的时刻,需 要重新调用getService.框架会在底层履行缓存操作,因此不存在太大的性能 问题.但重要的是,它答应数据库服务在线被替换成新的服务,假如没有缓存代 码,那么下次调用时,client将透明地绑定到新服务上.


  以上是“模块化Java:动态模块化[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:

  • 模块化Java:动态模块化
  • 模块化Java:声明式模块化
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .