2013-10-14 47 views
0

從這個問題:How to define a List bean in Spring?我知道我可以定義一個填充了Foo bean實例但使用XML配置的List<Foo> fooList。這裏有一個例子:如何使用註釋創建充滿原型bean實例的列表?

public interface Foo { 
    //methods here... 
    void fooMethod(); 
} 

@Service("foo") 
@Scope("prototype") 
public class FooImpl implements Foo { 
    //fields and methods... 
    @Override 
    public void fooMethod() { 
     //... 
    } 
} 

@Service("fooCache") 
@Scope 
public class FooCacheImpl implements Foo { 
    //fields and methods... 
    @Override 
    public void fooMethod() { 
     //retrieves data from some cache 
     //... 
    } 
} 

@Service("fooWS") 
@Scope("prototype") 
public class FooWSImpl implements Foo { 
    //fields and methods... 
    @Override 
    public void fooMethod() { 
     //retrieves data from web service 
     //... 
    } 
} 

我可以通過XML配置客戶端:

<bean id="fooClient" class="some.package.FooClient"> 
    <property name="fooList"> 
     <list> 
      <bean ... /> <!-- This may be fooImpl --> 
      <bean ... /> <!-- This may be fooCacheImpl --> 
      <bean ... /> <!-- This may be fooWSImpl --> 
      <!-- I can have more beans here --> 
     </list> 
    </property> 
</bean> 

我想知道這是否可以說明做而已,沒有必要通過XML定義bean。事情是這樣的:

@Component 
@Scope("prototype") 
public class FooClient { 
    //which annotation(s) to use here to fill this list with FooImpl instances? 
    //I understand that if I have two implementations of Foo I may use a @Qualifier 
    //or use another list to note the different implementations. 
    private List<Foo> fooList; 

    public void bar() { 
     for (Foo foo : fooList) { 
      foo.fooMethod(); 
     } 
    } 
} 

我認爲這將是更好的,不涉及注入ApplicationContext也不BeanFactory所以FooClient不緊耦合到Spring類的解決方案。另外,對於我的情況,我不能使用任何Java EE類,如javax.inject.Provider,如本博文所示:Spring 2.5.x+3.0.x: Create prototype instances from code

+0

你想創造出許多在列表中的同一個bean的? –

+0

您可以創建許多帶註釋的setter注入,每個注入的setter類型都是bean,並將bean添加到封裝列表中 –

+0

您的List中原型的實例數量是多少? –

回答

1

使用Factory Bean怎麼樣?

我知道你剛纔提到你並不想過度耦合到一個工廠bean,包含這個列表的bean並不那麼耦合 - 只是你的工廠。

喜歡的東西

@Component("fooList") 
class ListFactory<List<Foo>> implements FactoryBean, ApplicationContextAware { 

    ApplicationContext context; 
    public List<Foo>> getObject() { 
      List<Foo> list = new ArrayList(); 
      list.add(context.getBean("foo"); 
      list.add(context.getBean("foo"); 
      return list; 
    } 

    public void setApplicationContext(ApplicationContext context) { 
      this.context = context; 
    } 

    public boolean isSingleton() { 
      return false; 
    } 
} 

@Component 
@Scope("prototype") 
class FooClient { 

    @Inject 
    @Named("footList") 
    private List<Foo> fooList; 

    public void bar() { 
     for (Foo foo : fooList) { 
      foo.fooMethod(); 
     } 
    } 
} 

還沒有嘗試過自己,或者有在那裏我需要它,所以我不知道它會工作的情況。

+0

隨着你給我們的細節,OP,我認爲這是正確的解決方案。請記住,如果稍後創建新的'Foo' bean,那些bean將不會被添加到'FooClient'列表中。 –

0

如果你在代碼中直接這樣做,那麼我想用PostConstruct註釋將要走的路:

@Component 
@Scope("prototype") 
public class FooClient { 

.... 

    @PostConstruct 
    public void init() throws Exception { 
     fooList = new ArrayList<Foo>(); 
     fooList.add(new FooImpl()); 
    } 

我認爲使用這種方法會更靈活,因爲我覺得你只有在FooImpl對象本身需要額外配置的情況下才會與註釋混雜在一起。

+0

事實是他們這樣做,但我有一個'init'方法來處理它(直到我有更好的主意)。 –

0

這是prototype範圍的限制(或特徵)。 The docs say this

相較於其它範圍,Spring不管理整個 生命週期bean原型的:容器初始化,配置, 或者是裝配一個原型對象,並把它給 客戶端,與沒有進一步記錄該原型實例。

所以春節後雙手它關閉給你,它不保留對任何對它的引用,因此不能自動裝配任何人進入你的fooList。如果你沒有添加@Autowired

@Autowired 
private List<Foo> fooList; 

它只是創建一個新的FooImpl對象,自動裝配,作爲單一的元素在你的List

如果您試圖保留創建的所有Foo實例的引用,那麼您很可能必須自己做。

+0

所以我需要一種工廠方法,它返回一個我想/需要的新的實例*手動*請求。有什麼好方法不涉及XML配置,也不需要在我的類中直接使用'BeanFactory'? –

+0

@LuiggiMendoza問題是你的組件都是'prototype' bean,所以無論你什麼時候請求,你都會得到一個新的實例。你能詳細談談你想達到的目標嗎? –

+0

我想用原型bean填充我的'Foo'接口的列表。就如此容易。這是增強流程的解決方案的一部分。爲了向解決方案添加多個線程,我必須創建更多'Foo'實例,每個線程一個,以避免多個線程訪問相同資源(這解釋了原型範圍的使用)的問題。 –

0

您可以使用方法注入,因爲這:

public class PrototypeClient { 

    protected abstract PrototypeBean createPrototype(); 

    private List<PrototypeBean> createPrototypeList() { 
     int listSize = calculateListSize(); 

     List<Prototype> result = new ArrayList<Prototype(listSize); 

     for (int i = 0; i < listSize; i++) { 
      result.add(createPrototype()); 
     } 
     return result; 
    } 

    private int calculateListSize() { 
     // do your stuff here 
    } 

    // ... 
} 

,並有一個Spring配置爲:

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
          http://www.springframework.org/schema/beans/spring-beans.xsd"> 

    <bean id="prototypeBean" 
      class="fully.qualified.class.name.of.Prototype" 
      scope="prototype" /> 

    <bean id="prototyeClient" 
      class="fully.qualified.class.name.of.PrototypeClient"> 
     <lookup-method name="createPrototype" bean="prototypeBean"/> 
    </bean> 
</beans>         
相關問題