2011-07-22 74 views
7

方法context.getBean(名稱,用戶)的文件說,春參數傳遞到工廠方法在運行時

允許指定明確的構造函數的參數/工廠方法 參數

但無論我做什麼(嘗試所有),以最合理的設置,當豆子在初始化過程中加載時得到這個結果:

org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'fileValidator' defined in 
PortletContext resource 
[/WEB-INF/classes/context/customer-form-portlet.xml]: Unsatisfied 
dependency expressed through constructor argument with index 0 of type 
[com.liferay.portal.model.User]: Ambiguous factory method argument 
types - did you specify the correct bean references as factory method 
arguments? 
    org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'fileValidator' defined in 
PortletContext resource 
[/WEB-INF/classes/context/customer-form-portlet.xml]: Unsatisfied 
dependency expressed through constructor argument with index 0 of type 
[com.liferay.portal.model.User]: Ambiguous factory method argument 
types - did you specify the correct bean references as factory method 
arguments? 

<bean id="fileValidator" 
     class="cz.instance.transl.validation.file.FileValidator" 
     factory-method="createInstance" /> 

private FileValidator(User user) { 
    this.user = user; 
} 

public static FileValidator createInstance(User user) { 
    return new FileValidator(user); 
} 

評論說,你可以做到這一點,但如果你在bean的XML definiton或者未指定構造函數的參數,它失敗。

回答

15

javadoc說:

ARGS - 參數如果創建使用顯式參數靜態工廠方法的原型使用。

所以bean定義必須是一個原型作用域的bean,即

<bean id="fileValidator" 
     scope="prototype" 
     class="cz.instance.transl.validation.file.FileValidator" 
     factory-method="createInstance" /> 
+0

不幸的是,即使原型也是如此。使用3.1.0.M2 – lisak

+0

@lisak:首先,停止使用beta版本,堅持穩定版本(例如3.0.x) – skaffman

+2

它必須是3.1.0.M2中的錯誤...它非常複雜在那裏找到原因,如果我找到了,我會試着提高票價。謝謝 – lisak

7

爲了調用你的工廠方法Spring需要訪問一個用戶實例來傳遞給createInstance。在這種情況下,我只是創建bean並使其在:

<bean id="user" class="something.something.User"> 
</bean> 

<bean id="validator" class="cz.instance.transl.validation.file.FileValidator" factory-method="createInstance"> 
    <constructor-arg ref="user"/> 
</bean> 
+2

- context.getBean(名稱,用戶)。 – lisak

6

您可以使用一個抽象工廠也設置工廠bean的屬性。這裏我們有一個ActionFactory來創建動作。

<bean id="actions_factory" class="com.imagina.control.actions.impl.ActionFactoryImpl"/> 

<bean id="load_person_action" class="com.imagina.control.actions.impl.LoadPersonAction" 
    factory-bean="actions_factory" factory-method="create"> 
    <constructor-arg value="load_person_action"/>  
</bean> 

要使用此配置,您必須在帳戶藉此幾點:

  1. 創建方法也不是一成不變的。現在屬於一個實例
  2. 構造函數arg是工廠方法的參數
10

閱讀跨越20個職位,我發現,這不是明顯的如何得到一個自定義的工廠方法採取在運行時的參數,尤其是因爲我們不得不使用constructor-arg標記並在上下文中將現有的bean引用爲下面的設置,並將所涉及的類用作靜態工廠方法。

<bean id="user" class="something.something.User" /> 

<bean id="fileValidator" 
     class="cz.instance.transl.validation.file.FileValidator" 
     factory-method="createInstance" > 
     <constructor-args ref="user" /> 
</bean> 

我把它通過提取在使用的bean的實例工作構造-ARG出的背景下,然後用您在運行時的工作值填充它。當你得到你的工廠生成的bean時,這個bean將被用作參數。

public class X { 

    public void callFactoryAndGetNewInstance() { 
     User user = context.getBean("user"); 
     user.setSomethingUsefull(...); 
     FileValidator validator = (FileValidator)context.getBean("fileValidator"); 
     ... 
    } 
} 

注爲法是不是在這種情況下有關這不能解決問使用context.getBean(ARG1,ARG2)的問題。它不是的原因是因爲所有這些bean都是單例,並且此時構造函數未被調用。無論如何,如果您在單用戶系統中工作,則無需擔心任何問題,因爲無論如何,您在任何時候都只有1個用戶bean!

但是,對於多用戶系統,您需要確保每個真實用戶都擁有唯一的User Bean,並且您在工廠方法調用中使用了正確的User bean。

爲了在多用戶系統中執行此操作,您需要將bean類型更改爲原型,並且應該創建一個表示工廠的FileValidator的bean(如果您計劃將依賴注入到工廠中)和另一個代表新實例的Bean FileValidator。他們都將是同一類的類型,但你必須給每個人一個獨特的名字。請看下圖:

<bean id="user" scope="prototype" class="something.something.User" /> 

<bean id="validatorFactory" 
      class="cz.instance.transl.validation.file.FileValidator"> 
    <constructor-arg value="something" /> 
</bean> 

<bean id="fileValidatorBean" 
      class="cz.instance.transl.validation.file.FileValidator" 
    scope="prototype" 
    factory-method="createInstance" > 
    <constructor-arg ref="user" /> 
</bean> 

,並在您想獲得從工廠這一新FileValidator的bean類,你可以使用下面的技巧:我說我需要傳遞運行時參數

public void someMethod() { 
    ... 
    User user = context.getBean("user"); 
    user.setSomethingUsefull(...); 

    FileValidator fileValidator = 
       (FileValidator)context.getBean("fileValidatorBean", 
               user); 
    ... 
} 
+0

我是新來的春天。我嘗試了你的建議方法,它對我來說非常合適。但我無法理解爲什麼我們需要兩個相同bean的引用(即validatorFactory和fileValidatorBean)。我嘗試過使用單個bean(即fileValidatorBean),但它不起作用。你能抽出一些時間來闡述原因嗎?請。 – mrugeshthaker