2013-06-05 34 views
3

我有大量的spring bean來封裝現有的業務邏輯。現在我正在從我的新Clojure Compojure應用程序中重新使用這些Spring Beans。我該怎麼做呢 ?如何在Clojure應用程序中使用Spring Bean?

我所尋找的是等效的Clojure這

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

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

是否有這樣做的一個Clojure的方式嗎?

+0

您是否知道沒有什麼是春天特有的在你的問題? – vemv

回答

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

是您的Java代碼的Clojure等價物。 ...是你想要做的下一件事。或者,如果你想返回mybean作爲整個事情的價值(或許這將是一個功能包):

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

注意點在ClassPathXmlApplicationContext.末;這是new的簡寫,如(new ClassPathXmlApplicationContext ...)

+0

是否有可能加載上下文以使其可用於所有函數,包括不同名稱空間/ .clj文件中的函數? – user193116

+0

你是說它應該是一個全球性的?如果是,那麼肯定,這與訪問全局函數(例如,通過調用它)沒有什麼不同。你可以將它定義爲一個Var,然後用'require' /'use'從其他名字空間中取出該Var。或者你可以讓你的應用程序的初始化函數把它放在它返回的任何狀態結構中(或者安裝在某個位置),然後讓你的函數以你喜歡的方式查找它。 –

3

我一直在使用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]))) 
相關問題