我一直在使用Spring和Clojure一段時間了。我必須承認越來越少地使用它,因爲Spring在Clojure世界中並不是真正必需的。在哪裏我發現它有用的是測試我的Spring配置和鍛鍊bean。首先,我如何使用我的代碼,然後是代碼本身。
使用
(&init "applicationContext.xml")
(with-spring [mybean myotherbean]
(.method mybean arg1 arg2 arg3)
(.method myotherbean arg))
&init
讀取Spring應用程序上下文和充塞它在一個變種。 with-spring
使用let
爲向量中的每個名稱調用getBean將其分配給同名變量。然後使用這些任務執行正文。
下面是代碼,使之發生
(declare ^:dynamic *spring-context*)
(defn load-context
"Load a Spring Framwork Application context based on the locations"
([parent locations]
(doto (new ClassPathXmlApplicationContext (into-array locations) parent)
.refresh))
([locations]
(new ClassPathXmlApplicationContext (into-array locations))))
(defn &init
"Define spring funcs and return the Spring Application Context."
[locs]
(let [ctx (load-context locs)]
(def ^:dynamic *spring-context* ctx)
ctx))
(defn get-bean
[context name] (. context getBean name))
(defmacro typed-bean [ctx key]
(let [rtnval (gensym "rtnval") cls (gensym "cls") ]
`(fn []
(let [bean# (get-bean ~ctx ~key)
~cls (.getType ~ctx ~key)]
(let [~(with-meta rtnval {:tag cls}) bean#] ~rtnval)))))
(defn create-bean-map
"Create a map of bean names (as keywords) to functions. Calling the function
will return the bean with the given name.
ctx - The Spring Application Context"
([ctx]
(let [names (seq (org.springframework.beans.factory.BeanFactoryUtils/beanNamesIncludingAncestors ctx))]
(apply hash-map (mapcat (fn [f]
[(keyword f) (typed-bean ctx f)]) names)))))
(defn &beans [] (create-bean-map (&ctx)))
(defn && "Get a bean. Accepts a string, symbol or keyword"
([name]
(if-let [f (get (&beans) (keyword name))] (f))))
(defmacro with-spring
[[& beans] & body]
`(let [badones# (filter (fn [b#] (not (&& b#))) ~(reduce conj [] (map keyword beans)))]
(if (seq badones#) (throw (IllegalArgumentException. (str "Undefined beans:" (apply str badones#)))))
(let ~(reduce conj []
(mapcat
(fn [b]
(vector
b
(list (list (keyword b) '(&beans)))))
beans))
[email protected])))
您是否知道沒有什麼是春天特有的在你的問題? – vemv