我有很多封装现有业务逻辑的spring bean。现在我希望在我的新 Clojure Compojure 应用程序中重用这些 Spring Bean。我该怎么做呢 ?
我正在寻找的是与此等效的 Clojure
Context context = new ClassPathXmlApplicationContext(....);
MyBean mybean = context.get("mybean", MyBean.class)
有没有 Clojure 方法可以做到这一点?
(let [context (ClassPathXmlApplicationContext. ...)
mybean (.get context "mybean" MyBean)]
...)
是您的 Java 代码的 Clojure 等价物。...
是你接下来想做什么。或者,如果您想mybean
作为整个事物的值返回(也许这将被包装在一个函数中):
(let [context (ClassPathXmlApplicationContext. ...)]
(.get context "mybean" MyBean))
ClassPathXmlApplicationContext.
注意;末尾的点 这是 的简写new
,如(new ClassPathXmlApplicationContext ...)
.
我已经使用 Spring 和 Clojure 有一段时间了。我必须承认越来越少地使用它,因为 Spring 在 Clojure 世界中并不是真正需要的。我发现它有用的地方是测试我的 Spring 配置和锻炼 bean。首先是我如何使用我的代码,然后是代码本身。
用法
(&init "applicationContext.xml")
(with-spring [mybean myotherbean]
(.method mybean arg1 arg2 arg3)
(.method myotherbean arg))
&init
读取 Spring 应用程序上下文并将其填充到 var 中。
with-spring
为向量中的每个名称调用 getBean 将其分配给同名的“变量”,使用let
. 然后使用这些分配执行主体。
这是实现它的代码
(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))
~@body)))