2015-07-01 90 views
2

鑑於這種類:,如何將項目添加到最終的,預填充列表?

public class Node { 
    private final List<Node> children; 
    public Node(){ 
    children = new ArrayList<>(); 
    // possibly pre-populate the list here 
    } 
    public List<Node> getChildren(){ 
    return children; 
    } 
} 

什麼是創建於春子節點的節點的最好方式,當一些孩子是由類和定義了一些應該是可配置?

<bean id="node1" class="Node"> 
    <property name="children"> 
    <add-item><bean class="Node"/></add-item> <!--pseudocode--> 
    <add-item><bean class="Node"/></add-item> <!--pseudocode--> 
    </property> 
</bean> 

的答案在我的Spring IoC文檔發現和論壇沒有滿足我,因爲提出的方案涉及不同程度的開銷:其他測繪豆,工廠方法,抽象豆從,繼承...那那裏有更優雅的東西?

+0

可能重複[?如何在Spring中定義一個列表豆(http://stackoverflow.com/問題/ 2416056 /如何定義列表bean-in-spring) – Timo

回答

3

我會去注入列表直接進入構造函數。這就不難使用最後一個字段:

public class Node { 
    private final List<Node> children; 
    public Node(List<Node> children){ 
    this.children = children; 
    } 
    public List<Node> getChildren(){ 
    return children; 
    } 
} 

<bean id="node1" class="Node"> 
    <constructor-arg> 
     <list> 
      <item><bean class="Node"/></item> <!--pseudocode--> 
      ... 
     </list> 
    </constructor-arg>  
</beans> 

編輯到您的評論:

如果你想之前或之後做初始化,你可以這樣做只是這樣的:

... 
public Node(List<Node> children){ 
    this.children = new ArrayList<>(); 
    // do some initialization before... 
    this.children.addAll(children); 
    // do some initialization after... 
} 
... 
+0

是的,很好的答案,但是,如果我在課堂上有預定義的項目,該怎麼辦? (編輯我的例子來澄清) – Markus

+0

好吧,我可以讓構造函數添加提供的項目之後prepopulated項目,這將做 – Markus

1

我改變Node類有點

public class Node implements InitializingBean{ 

private final List<Node> children; 

private String name; 

public Node() { 
    children = new ArrayList<>(); 
} 

@Override 
public void afterPropertiesSet() throws Exception { 
    //predefined nodes 
    Node node = new Node(); 
    node.setName(":)"); 
    children.add(node); 
} 

public String toString(){ return name; } 

public List<Node> getChildren() { 
    return children; 
} 

public void setNodes(Node nodes[]){ 
    if(nodes != null){ 
     for(Node node: nodes){ 
      this.children.add(node); 
     } 
    } 
} 

public void setChildren(Object something){ 
    System.out.println(something.getClass()); 
} 
public void setName(String name) { this.name = name; } 

}

訣竅是迭代參數值並添加到預定義的數組列表中。 我之所以把它命名爲setNodes而不是setChildren,是因爲Spring會反思getChildren的兒童房產類型。如果我將設置者命名爲setChildren,我將獲得IllegalArgumentException

當然,我可以使用ArrayList而不是本地數組,但你說你不想要任何開銷。創建數組就不算什麼,從數組添加對象到ArrayList只是創建一個便宜的參考。

這是bean定義

<bean id="node1" class="playground.Node"> 
    <property name="nodes"> 
     <array > 
      <bean class="playground.Node"> 
       <property name="name" value="A" /> 
      </bean> 
      <bean class="playground.Node"> 
       <property name="name" value="B" /> 
      </bean> 
     </array> 
    </property> 
</bean> 
+0

是的,我也想到了一個列表屬性,可讀,代表所有孩子和第二個列表屬性,可寫,添加孩子。它確實有效,並沒有那麼糟糕,但仍然感覺像「將域模型調整爲Spring功能」而不是「使用Spring來適應域模型」 – Markus

+0

如果您根本不想修改模型類,則應該使用Spring java配置代替。另一個解決方法是使用'MethodInvokingFactoryBean'來調用'add'方法,但除非Spring XML支持循環,否則它非常繁瑣而且不夠優雅。 – hussachai

1

你沒有指定兒童的來源。作爲第二選項,您可以使用@PostContruct方法,如果您不希望注入到列表contstructor:

public class Node { 
    private final List<Node> children; 
    public Node(){ 
    children = new ArrayList<>(); 
    } 
    public List<Node> getChildren(){ 
    return children; 
    } 

    @PostConstruct 
    public void init() { 
    // this method will Spring call after dependency injection is done. 
    children.add(...) 
    }