I'm using Spring to define stages in my application. It's configured that the necessary class (here called Configurator) is injected with the stages.
Now I need the List of Stages in another class, named LoginBean. The Configurator doesn't offer access to his List of Stages.
I cannot change the class Configurator.
My Idea:
Define a new bean called Stages and inject it to Configurator and LoginBean. My problem with this idea is that I don't know how to transform this property:
<property ...> <list> <bean ... >...</bean> <bean ... >...</bean> <bean ... >...</bean> </list> </property> into a bean.
Something like this does not work:
<bean> Can anybody help me with this?
13 Answers
Import the spring util namespace. Then you can define a list bean as follows:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="" xmlns:xsi="" xmlns:util="" xsi:schemaLocation=" "> <util:list value-type="java.lang.String"> <value>foo</value> <value>bar</value> </util:list> The value-type is the generics type to be used, and is optional. You can also specify the list implementation class using the attribute list-class.
Here is one method:
<bean/> <bean/> <bean> <constructor-arg> <list> <ref bean="stage1" /> <ref bean="stage2" /> </list> </constructor-arg> </bean> 5Another option is to use JavaConfig. Assuming that all stages are already registered as spring beans you just have to:
@Autowired private List<Stage> stages; and spring will automatically inject them into this list. If you need to preserve order (upper solution doesn't do that) you can do it in that way:
@Configuration public class MyConfiguration { @Autowired private Stage1 stage1; @Autowired private Stage2 stage2; @Bean public List<Stage> stages() { return Lists.newArrayList(stage1, stage2); } } The other solution to preserve order is use a @Order annotation on beans. Then list will contain beans ordered by ascending annotation value.
@Bean @Order(1) public Stage stage1() { return new Stage1(); } @Bean @Order(2) public Stage stage2() { return new Stage2(); } <bean> <property name="myList"> <list value-type="com.somePackage.TypeForList"> <ref bean="someBeanInTheList"/> <ref bean="someOtherBeanInTheList"/> <ref bean="someThirdBeanInTheList"/> </list> </property> </bean> And in SomeClass:
class SomeClass { List<TypeForList> myList; @Required public void setMyList(List<TypeForList> myList) { this.myList = myList; } } 1Stacker posed a great answer, I would go one step farther to make it more dynamic and use Spring 3 EL Expression.
<bean> <constructor-arg> <value>#{springDAOBean.getGenericListFoo()}</value> </constructor-arg> </bean> I was trying to figure out how I could do this with the util:list but couldn't get it work due to conversion errors.
1I think you may be looking for org.springframework.beans.factory.config.ListFactoryBean.
You declare a ListFactoryBean instance, providing the list to be instantiated as a property withe a <list> element as its value, and give the bean an id attribute. Then, each time you use the declared id as a ref or similar in some other bean declaration, a new copy of the list is instantiated. You can also specify the List class to be used.
<bean> <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> define those beans(test1,test2) afterwards :)
Inject list of strings.
Suppose you have Countries model class that take list of strings like below.
public class Countries { private List<String> countries; public List<String> getCountries() { return countries; } public void setCountries(List<String> countries) { this.countries = countries; } } Following xml definition define a bean and inject list of countries.
<bean name="demoCountryCapitals"> <property name="countries"> <list> <value>Iceland</value> <value>India</value> <value>Sri Lanka</value> <value>Russia</value> </list> </property> </bean> Reference link
Inject list of Pojos
Suppose if you have model class like below.
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; } } Bean Definitions.
<bean> <property name="name" value="India" /> <property name="capital" value="New Delhi" /> </bean> <bean> <property name="name" value="Russia" /> <property name="capital" value="Moscow" /> </bean> <bean name="demoCountryCapitals"> <property name="favoriteCountries"> <list> <ref bean="india" /> <ref bean="russia" /> </list> </property> </bean> Reference Link.
Use the util namespace, you will be able to register the list as a bean in your application context. You can then reuse the list to inject it in other bean definitions.
As an addition to Jakub's answer, if you plan to use JavaConfig, you can also autowire that way:
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); } } You just remove id out of beans inside <list> tag. Like this:
<property name="listStaff"> <list> <bean> <constructor-arg name="name" value = "Jonh"/> <constructor-arg name="age" value = "30"/> </bean> <bean> <constructor-arg name="name" value = "Jam"/> <constructor-arg name="age" value = "21"/> </bean> </list> </property> Use list-class attribute in util:list to make a standalone list of any particular type. for example if you want to make list of type ArrayList:
<util:list list-class="java.util.ArrayList" value-type="java.lang.String"> <value>Abhay</value> <value>ankit</value> <value>Akshansh</value> <value>Db</value> </util:list> or if you want to make a list of type LinkedList then :
<util:list list-class="java.util.LinkedList" value-type="java.lang.String"> <value>Abhay</value> <value>ankit</value> <value>Akshansh</value> <value>Db</value> </util:list> And this is how to inject set in some property in Spring:
<bean> <property name="stages"> <set value-type="biz.bsoft.AbstractStage"> <ref bean="stageReady"/> <ref bean="stageSteady"/> <ref bean="stageGo"/> </set> </property> </bean>