调整用于导入的类加载器

时间:2019-04-04 18:07:34

标签: clojure

在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,但是随着我的项目越来越大,使用它时遇到了一些问题。)

0 个答案:

没有答案