8

我想在项目更新之间进行热代码交换,但我还没有找到有关如何动态加载 .class 文件的任何信息。更具体地说,我想要这样的东西:

  1. 制作lein uberjar,获得some-client-0.0.0-standalone.jar
  2. 运行它java -jar some-client-0.0.0-standalone.jar
  3. 对项目进行更改。获取新的程序版本,some-client-0.0.1-standalone.jar复制到some-client-0.0.0-standalone.jar目录。
  4. 客户端接收更新到新版本所需的命令序列。
  5. (可选)更新资源。不再使用旧 jar 中的资源。
  6. (可选)some-client-0.0.0-standalone.jar现在可以删除。
4

2 回答 2

6

插件框架方法

您已经说过您想要进行热代码交换,但您真正需要的是松散耦合的模块以及在运行时进行解析的能力。坦率地说,任何插件框架都可能有所帮助,包括成熟的 OSGi(将在下面介绍)。

在此处输入图像描述

由于您正在执行某种 PoC,我建议您查看以下示例:

  1. 您有一个定义了一些扩展点(隐喻解释)的元应用程序
  2. 要升级或替换的功能将作为松散耦合的模块(插件)实现
  3. 元应用程序通过请求或自动执行解析以查找更新的“功能”(根据定义的扩展点)

可以提出定义simlle升级方案:

  1. 用户使用应用程序
  2. 用户安装(复制)具有一个或多个扩展点的新实现的 JAR(其他类型的包)
  3. 用户触发全局系统解析或系统扫描新更新或系统执行解析每个用户尝试访问某些功能

以这种方式,元应用程序将能够提供新的或更新的功能而无需重新启动。这样你就可以:

  1. 尝试使用一些简单的 java 插件框架(例如,Java Simple Plugin Framework。5 分钟就可以了。没有 XML。这种方法似乎有点难看
  2. 使用 clojure 的动态特性,正如这里所建议的那样

您还可以查看并采用 Waterfront(基于 Clojure 的 Clojure 编辑器)调查结果(可能需要它来增强生命周期管理等)

在实现方面,Waterfront 是基于上下文模式的。它允许事件处理程序以功能(无副作用)的方式进行通信。除此之外,还有一个插件加载器机制,它加载在 Waterfront 的配置文件中指定的插件。这意味着可以轻松添加或删除功能(在调试时非常有用!)。

OSGI 方法

正如建议的那样,OSGi 似乎是解决您的问题的好方法。另请注意,OSGi 是好的、成熟的,并且提供了很多开箱即用的东西,但它也有些复杂:

在此处输入图像描述

顺便说一句,OSGi 是 clojure 社区的长期目标。您可以检查Clojure Todo

> better modularization for OSGi etc 
>  * names
>  * no single namespace pool
>  * namespaces found via classes, thus tracks classloader and modules 
>  * deal with import proxying a la Class.forName stack walk?

已经有一些解决方案可用:

  1. clojure-osgi-utils
  2. clojure.osgi

第二个项目提供了使用 clojure 和 OSGi 的 Producer-Consumer 示例:

快乐编码。

于 2013-03-06T21:39:03.793 回答
2

要在运行时严格从 jar 文件重新加载,您可能需要查看OSGi 类加载器。对于 Clojure 代码,您可以在侦听本地端口的客户端中启动 nrepl,然后当您想要重新加载连接到该端口的代码并调用load-file

于 2013-02-28T22:00:16.693 回答