如何在Clojure应用程序中使用Spring Beans?

5

我有很多封装现有业务逻辑的Spring Bean。现在我想从我的新Clojure Compojure应用程序中重用这些Spring Bean。我该怎么做?

我要找到Clojure版本的等价代码。

Context context = new ClassPathXmlApplicationContext(....);

MyBean mybean = context.get("mybean", MyBean.class)

有没有使用Clojure的方法来完成这个任务?

你是否意识到你的问题中没有任何与Spring相关的内容? - deprecated
2个回答

6
(let [context (ClassPathXmlApplicationContext. ...)
      mybean  (.get context "mybean" MyBean)]
  ...)

Clojure是您Java代码的等效物。 ... 是您想要执行的任何操作。或者,如果您想将mybean作为整个值返回(也许这将被包装在一个函数中):

(let [context (ClassPathXmlApplicationContext. ...)]
  (.get context "mybean" MyBean))

请注意 ClassPathXmlApplicationContext. 结尾的点号; 这是用于代替 new 的简写方式,例如 (new ClassPathXmlApplicationContext ...)

是否可以加载上下文,使其对所有函数都可用,包括不同命名空间/.clj文件中的函数? - user193116
你的意思是它应该有效地成为一个全局变量吗?如果是的话,那当然可以,这与访问全局函数没有区别(例如通过调用它)。你可以将其def为一个变量,然后使用require/use从其他命名空间中引入该变量;或者你可以让你的应用程序的初始化函数将其放入它返回的任何状态结构(或安装在某个位置),然后让你的函数以你喜欢的任何方式查找它。 - Michał Marczyk

5

我已经使用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)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接