您在类加载器方面遇到的问题是可以预料的:如果您的 Eclipse 插件/OSGi 捆绑包的依赖项是 A -> B,并且 Clojure jar 从 B 引导,则无法从 B 中看到 A 的资源是正常的。
Eclipse 插件的依赖关系之间不能有循环,因此类加载器层次结构之间不能有循环。
如果您要使用常规 Eclipse 机器从 A 向 B 编写扩展,这与您将面临的问题相同:插件 B 将声明一个接口和一个扩展点。然后插件 A 可以实现接口,并声明扩展点的扩展。最后一部分允许 Eclipse 框架对包做一些技巧:它看到 A 声明了对 B 的扩展,因此从 A 中实例化了一个类,实现了在 B 中声明的接口(这有效,因为 A 依赖于 B),并给 B来自 A 的实现实例也可以,因为它实现了 B 中的接口!
(不确定这是否清楚)。
无论如何,回到用 Clojure 编写的插件。
使用 Clojure,您没有开箱即用的类加载器提供的这种单独的环境,因为所有内容都聚合在一个“Clojure 环境”中,该环境位于嵌入 clojure jar 的插件的类加载器领域中。因此,一种可能性是,当插件 A 启动时,从 A 加载相关的命名空间。然后它们将在正确的时间加载,并可供任何其他 Clojure 代码使用。另一种可能性是使用扩展点/扩展机器。Eclipse 提供了一种使用“工厂”创建扩展点实例的方法。在逆时针方向,我们利用了这个特性,并有一个通用工厂类(用 java 编写,所以没有 AOT)负责从正确的包中加载正确的命名空间。
这里有更多关于如何扩展扩展点的细节。
逆时针的一个例子:
Eclipse 框架中有一个现有的扩展点,用于为控制台内容提供超链接检测器。逆时针扩展此扩展点以添加 nrepl 超链接。
在 Java 世界中,您必须在您的扩展中直接声明您的某个实现接口 IPatternMatchListenerDelegate 的类。
但是对于CCW,可能出于与您相同的原因,我会不惜一切代价避免AOT,所以我不能在扩展中给出java类名,或者我不得不用java编写并编译它,或者gen-class
在 Clojure 中编写一个并 AOT 编译它。
相反,CCW 充分利用了 plugin.xml 的可能性:几乎在每个地方,当您必须提供类名时,您可以提供一个IExecutableExtensionFactory的实例, create()
Eclipse 框架将调用它的方法来创建想要的班级。
这使我可以编写一个通用类来调用 Clojure 世界:我只是使用类名ccw.util.GenericExecutableExtension代替我应该编写的类名
从plugin.xml中提取:
<extension point="org.eclipse.ui.console.consolePatternMatchListeners">
<consolePatternMatchListener
id="ccw.editors.clojure.nREPLHyperlink"
regex="nrepl://[^':',' ']+:\d+">
<class class="ccw.util.GenericExecutableExtension">
<parameter
name="factory"
value="ccw.editors.clojure.nrepl-hyperlink/factory">
</parameter>
</class>
</consolePatternMatchListener>
注意class
属性,以及如何通过parameter
元素为工厂提供参数(工厂必须实现接口IExecutableExtension才能使用参数进行初始化)。
最后,您可以看到在 namespaceccw.editors.clojure.nrepl-hyperlink
中,函数工厂非常简单,只需调用make函数:
(defn make []
(let [state (atom nil)]
(reify org.eclipse.ui.console.IPatternMatchListenerDelegate
(connect [this console] (dosync (reset! state console)))
(disconnect [this] (reset! state nil))
(matchFound [this event] (match-found event @state)))))
(defn factory "plugin.xml hook" [ _ ] (make))
请注意,我将其作为示例进行展示,并且逆时针方向的相关代码尚未准备好作为独立库“可供使用”发布。
但是您仍然应该能够推出自己的解决方案(一旦您将所有部分都放在脑海中就很容易了)。
希望有帮助,
——洛朗