我有很多封装现有业务逻辑的Spring Bean。现在我想从我的新Clojure Compojure应用程序中重用这些Spring Bean。我该怎么做?
我要找到Clojure版本的等价代码。
Context context = new ClassPathXmlApplicationContext(....);
MyBean mybean = context.get("mybean", MyBean.class)
有没有使用Clojure的方法来完成这个任务?
我有很多封装现有业务逻辑的Spring Bean。现在我想从我的新Clojure Compojure应用程序中重用这些Spring Bean。我该怎么做?
我要找到Clojure版本的等价代码。
Context context = new ClassPathXmlApplicationContext(....);
MyBean mybean = context.get("mybean", MyBean.class)
(let [context (ClassPathXmlApplicationContext. ...)
mybean (.get context "mybean" MyBean)]
...)
Clojure是您Java代码的等效物。 ...
是您想要执行的任何操作。或者,如果您想将mybean
作为整个值返回(也许这将被包装在一个函数中):
(let [context (ClassPathXmlApplicationContext. ...)]
(.get context "mybean" MyBean))
ClassPathXmlApplicationContext.
结尾的点号; 这是用于代替 new
的简写方式,例如 (new ClassPathXmlApplicationContext ...)
。def
为一个变量,然后使用require
/use
从其他命名空间中引入该变量;或者你可以让你的应用程序的初始化函数将其放入它返回的任何状态结构(或安装在某个位置),然后让你的函数以你喜欢的任何方式查找它。 - Michał Marczyk我已经使用Spring和Clojure有一段时间了。我必须承认在Clojure的世界里,我越来越少地使用它,因为Spring并不是真正必要的。但我发现它在测试我的Spring配置和运用bean方面非常有用。首先介绍我的代码使用方式,然后是代码本身。
使用方法
(&init "applicationContext.xml")
(with-spring [mybean myotherbean]
(.method mybean arg1 arg2 arg3)
(.method myotherbean arg))
&init
读取 Spring 应用上下文并将其存储在一个变量中。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)))