在Clojure中使用import
表单时,我希望该表单使用Janino library中的JavaSourceClassLoader
,以便在尝试导入类时,此自定义加载程序将在内部Java源目录,并即时编译要导入的Java类。
在我的Leiningen项目的根目录中,我有一个dynjava/
目录,在该目录中放置了Java源文件。我写了一些代码来构造JavaSourceClassLoader:
(ns playground.classloading
(:import [org.codehaus.janino JavaSourceClassLoader])
(:require [clojure.java.io :as io]))
(defn current-loader []
(.deref clojure.lang.Compiler/LOADER))
(defn make-source-loader
([]
(make-source-loader (current-loader)))
([parent]
(JavaSourceClassLoader.
parent
(into-array [(io/file "dynjava")])
nil)))
我有一个示例文件dynjava/Magic.java
,如下所示,以便对其进行测试:
public class Magic {
public int getNumber() {
return 119;
}
}
实际上,我可以在REPL中编译,加载和创建此类的实例,例如
(.getNumber (.newInstance (.loadClass (make-source-loader) "Magic")))
;; => 119
现在,我想将JavaSourceClassLoader与import
表单一起使用,因此我尝试了以下操作:
(def src-loader (make-source-loader))
(.bindRoot clojure.lang.Compiler/LOADER src-loader)
(.set clojure.lang.Compiler/LOADER src-loader)
(println "The var is " clojure.lang.Compiler/LOADER)
(if (.isBound clojure.lang.Compiler/LOADER)
(println "The compiler loader is "
(.deref clojure.lang.Compiler/LOADER)))
显示以下内容:
The var is #<Var: --unnamed--> The compiler loader is #object[clojure.lang.DynamicClassLoader 0x9b1fcd3 clojure.lang.DynamicClassLoader@9b1fcd3] playground.classloading>
从此输出中很明显,尝试修改LOADER
var时我做错了,因为它不是JavaSourceClassLoader
的实例。
尝试导入我之前编写的Magic
类无效:
;; (import 'Magic) results in an Error
我的问题是:如何将Clojure中import
使用的类加载器更改为JavaSourceClassLoader的实例?
(顺便说一下,我知道lein-virgil
,但是随着我的项目越来越大,使用它时遇到了一些问题。)