Comment définir un bean List au printemps?

203

J'utilise Spring pour définir les étapes de mon application. Il est configuré pour Configuratorinjecter la classe nécessaire (appelée ici ) avec les étapes.
Maintenant, j'ai besoin de la liste des étapes d'une autre classe, nommée LoginBean. Le Configuratorne donne pas accès à sa liste d'étapes.

Je ne peux pas changer de classe Configurator.

Mon idée:
définir un nouveau bean appelé Stages et l'injecter dans Configuratoret LoginBean. Mon problème avec cette idée est que je ne sais pas comment transformer cette propriété:

<property ...>
  <list>
    <bean ... >...</bean>
    <bean ... >...</bean>
    <bean ... >...</bean>
  </list>
</property>

dans un haricot.

Quelque chose comme ça ne fonctionne pas:

<bean id="stages" class="java.util.ArrayList">

Quelqu'un peut-il m'aider avec ça?

guerda
la source

Réponses:

279

Importez l'espace de noms Spring util. Ensuite, vous pouvez définir un bean de liste comme suit:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                    http://www.springframework.org/schema/util
                    http://www.springframework.org/schema/util/spring-util-2.5.xsd">


<util:list id="myList" value-type="java.lang.String">
    <value>foo</value>
    <value>bar</value>
</util:list>

Le type de valeur est le type générique à utiliser et est facultatif. Vous pouvez également spécifier la classe d'implémentation de liste à l'aide de l'attribut list-class.

simonlord
la source
10
et évidemment le contenu de la liste peut être des valeurs, des références et des beans etc.
simonlord
Merveilleuse réponse, c'est plus "printanier"
jpaoletti
1
simple:<property name="beanList" ref="myList"/>
Manuel Spigolon
1
Salut, je reçois ce type de cvc-complex.2.4.c: Le caractère générique correspondant est strict, mais aucune déclaration ne peut être trouvée pour l'élément 'value'. J'ai ajouté l'espace de noms et le schémaLocation still
vishal
17
Je viens de remarquer que cela @Autwiredn'aide pas lors de l'injection d'une liste créée de cette façon. Cependant, @Resourceça marche. soit@Resource List<String> myList
Matt Friedman
173

Voici une méthode:

<bean id="stage1" class="Stageclass"/>
<bean id="stage2" class="Stageclass"/>

<bean id="stages" class="java.util.ArrayList">
    <constructor-arg>
        <list>
            <ref bean="stage1" />
            <ref bean="stage2" />                
        </list>
    </constructor-arg>
</bean>
gerbeur
la source
1
+1 - Je ne savais pas que vous pouviez faire cela (bien que je puisse voir que cela devrait fonctionner). Suggestion: Je pense que vous devriez pouvoir intégrer les StageClassdéclarations de bean en <list>évitant le besoin d' <ref>éléments.
Stephen C
9
vous pouvez également utiliser util: list pour vous donner un arraylist
Richard
Est-il possible d'incorporer ces définitions de bean dans "<list> </list>"?
Sefler
@Sefler oui, les définitions devraient y être identiques
eis
Il y a un piège: si vous utilisez @Autowired, assurez-vous que votre pojo est également de type "ArrayList" et pas seulement "List" ou vous pourriez obtenir quelque chose de complètement différent.
Tilman Hausherr
38

Une autre option consiste à utiliser JavaConfig. En supposant que toutes les étapes sont déjà enregistrées comme haricots de printemps, il vous suffit de:

@Autowired
private List<Stage> stages;

et le printemps les injectera automatiquement dans cette liste. Si vous devez préserver l'ordre (la solution supérieure ne le fait pas), vous pouvez le faire de cette façon:

@Configuration
public class MyConfiguration {
  @Autowired
  private Stage1 stage1;

  @Autowired
  private Stage2 stage2;

  @Bean
  public List<Stage> stages() {
    return Lists.newArrayList(stage1, stage2);
  }
}

L'autre solution pour conserver l'ordre est d'utiliser une @Orderannotation sur les beans. La liste contiendra alors les beans classés par valeur d'annotation ascendante.

@Bean
@Order(1)
public Stage stage1() {
    return new Stage1();
}

@Bean
@Order(2)
public Stage stage2() {
    return new Stage2();
}
Jakub Kubrynski
la source
34
<bean id="someBean"
      class="com.somePackage.SomeClass">
    <property name="myList">
        <list value-type="com.somePackage.TypeForList">
            <ref bean="someBeanInTheList"/>
            <ref bean="someOtherBeanInTheList"/>
            <ref bean="someThirdBeanInTheList"/>
        </list>
    </property>
</bean>

Et dans SomeClass:

class SomeClass {

    List<TypeForList> myList;

    @Required
    public void setMyList(List<TypeForList> myList) {
        this.myList = myList;
    }

}
Koray Tugay
la source
8

Stacker a posé une excellente réponse, j'irais plus loin pour le rendre plus dynamique et utiliser Spring 3 EL Expression.

<bean id="listBean" class="java.util.ArrayList">
        <constructor-arg>
            <value>#{springDAOBean.getGenericListFoo()}</value>
        </constructor-arg>
</bean>

J'essayais de comprendre comment je pouvais faire cela avec la liste util: mais je ne pouvais pas le faire fonctionner en raison d'erreurs de conversion.

haju
la source
4

Je pense que vous cherchez peut-être org.springframework.beans.factory.config.ListFactoryBean.

Vous déclarez une instance ListFactoryBean, en fournissant la liste à instancier en tant que propriété avec un <list>élément comme valeur, et donnez au bean un idattribut. Ensuite, chaque fois que vous utilisez le déclaré idcomme refou similaire dans une autre déclaration de bean, une nouvelle copie de la liste est instanciée. Vous pouvez également spécifier la Listclasse à utiliser.

Stephen C
la source
C'est un bon indice, mais je ne le fais pas fonctionner. La réponse de Stakker a fonctionné. +1 pour l'indice.
guerda
2
 <bean id="student1" class="com.spring.assin2.Student">  
<property name="name" value="ram"></property>  
<property name="id" value="1"></property> 
<property name="listTest">
        <list value-type="java.util.List">
            <ref bean="test1"/>
            <ref bean="test2"/>
        </list>
    </property>
</bean>  

définir ces beans (test1, test2) après :)

RaM PrabU
la source
1

Utilisez l'espace de noms util, vous pourrez enregistrer la liste en tant que bean dans votre contexte d'application. Vous pouvez ensuite réutiliser la liste pour l'injecter dans d'autres définitions de bean.

Juan Perez
la source
1

En complément de la réponse de Jakub, si vous prévoyez d'utiliser JavaConfig, vous pouvez également câbler automatiquement de cette façon:

import com.google.common.collect.Lists;

import java.util.List;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;

<...>

@Configuration
public class MyConfiguration {

    @Bean
    public List<Stage> stages(final Stage1 stage1, final Stage2 stage2) {
        return Lists.newArrayList(stage1, stage2);
    }
}
Jose Alban
la source
1

Vous venez de supprimer idles haricots à l'intérieur de la <list>balise. Comme ça:

<property name="listStaff">
  <list>
    <bean class="com.test.entity.Staff">
        <constructor-arg name="name" value = "Jonh"/>
        <constructor-arg name="age" value = "30"/>
    </bean>
    <bean class="com.test.entity.Staff">
        <constructor-arg name="name" value = "Jam"/>
        <constructor-arg name="age" value = "21"/>
    </bean>
  </list>
</property>
dqthe
la source
0

Et voici comment injecter un ensemble dans une propriété au printemps:

<bean id="process"
      class="biz.bsoft.processing">
    <property name="stages">
        <set value-type="biz.bsoft.AbstractStage">
            <ref bean="stageReady"/>
            <ref bean="stageSteady"/>
            <ref bean="stageGo"/>
        </set>
    </property>
</bean>
Slava Babin
la source
0

Injectez la liste des chaînes.

Supposons que vous ayez une classe de modèle Pays qui accepte une liste de chaînes comme ci-dessous.

public class Countries {
    private List<String> countries;

    public List<String> getCountries() {
        return countries;
    }   

    public void setCountries(List<String> countries) {
        this.countries = countries;
    }

}

Après la définition xml, définissez une liste de bean et inject de pays.

<bean id="demoCountryCapitals" name="demoCountryCapitals" class="com.sample.pojo.Countries">
   <property name="countries">
      <list>
         <value>Iceland</value>
         <value>India</value>
         <value>Sri Lanka</value>
         <value>Russia</value>
      </list>
   </property>
</bean>

Lien de référence

Injecter la liste des Pojos

Supposons que vous ayez une classe de modèle comme ci-dessous.

public class Country {
    private String name;
    private String capital;
    .....
    .....
 }

public class Countries {
    private List<Country> favoriteCountries;

    public List<Country> getFavoriteCountries() {
        return favoriteCountries;
    }

    public void setFavoriteCountries(List<Country> favoriteCountries) {
        this.favoriteCountries = favoriteCountries;
    }

}

Définitions du bean.

 <bean id="india" class="com.sample.pojo.Country">
  <property name="name" value="India" />
  <property name="capital" value="New Delhi" />
 </bean>

 <bean id="russia" class="com.sample.pojo.Country">
  <property name="name" value="Russia" />
  <property name="capital" value="Moscow" />
 </bean>


 <bean id="demoCountryCapitals" name="demoCountryCapitals" class="com.sample.pojo.Countries">
  <property name="favoriteCountries">
   <list>
    <ref bean="india" />
    <ref bean="russia" />
   </list>
  </property>
 </bean>

Lien de référence .

Hari Krishna
la source