Настройка загрузчика классов, используемого для импорта

#clojure

#clojure

Вопрос:

При использовании import формы в Clojure я бы хотел, чтобы эта форма использовала JavaSourceClassLoader из библиотеки Janino, чтобы при попытке импортировать класс этот пользовательский загрузчик просматривал исходный каталог 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
  

Мой вопрос: как я могу изменить загрузчик классов, используемый import в Clojure, чтобы он был экземпляром JavaSourceClassLoader?

(Кстати, я в курсе lein-virgil , но у меня возникли некоторые проблемы с его использованием по мере того, как мой проект разрастался.)