Spring - Injecting Arrays and Collections

[Updated: May 10, 2017, Created: Aug 16, 2016]

Spring XML based configuration defined elements like <list/>, <set/>, <map/>, and <props/>. The purpose of these elements was to map XML based configuration to Java arrays and collection. Since the addition of JavaConfig, we don't required that kind of custom mappings because new configuration is itself in Java language instead of XML.

In following examples, we will learn how to use arrays and collection in JavaConfig.

  1. Array Injection:

    In XML configuration, we use <list/> element for mapping Java arrays. In JavaConfig we can straight inject the arrays by returning an array instance as @Bean:

    @Configuration
    public class ArrayExample {
        @Bean
        public TestBean testBean () {
            return new TestBean();
        }
    
        @Bean
        public String[] strArray(){
            return new String[]{"two", "three", "four"};
        }

     public class TestBean {
            private  String[] stringArray;
    
            @Autowired
            public void setStringArray (String[] stringArray) {
                this.stringArray = stringArray;
            }
    
               ....
        }

    We can also inject arrays of user defined object instead of simple arrays. With all arrays and collections we can use constructor, setter or field injections.



  2. Collections Injection:

    We can also inject any java.util.Collection implementation just like above example.

    public class ListExample {
        @Bean
        public TestBean testBean () {
            return new TestBean();
        }
    
        @Bean
        public List<String> strList(){
            return Arrays.asList("two", "three", "four");
        }

     public class TestBean {
            private  List<String> stringList;
    
            @Autowired
            public void setStringList (List<String> stringList) {
                this.stringList = stringList;
            }
                ...
    
        }


  3. Map Injection:

    Just like above two examples we can expose a Map instance as bean (using @Bean) ready to be injected at intended injection points.



  4. Injecting individual beans as array/collections/map elements:

    Instead of exposing a complete array/collections/map instance as bean, we can create individual beans (using @Bean) of same type which can be injected by the spring container to a single collection (the injection point). Here's a Set example:


    @Configuration
    public class SetInjection {
    
        @Bean
        public TestBean testBean () {
            return new TestBean();
        }
    
        @Bean
        public RefBean refBean1 () {
            return new RefBean("bean 1");
        }
    
        @Bean
        public RefBean refBean2 () {
            return new RefBean2("bean 2");
        }
    
        @Bean
        public RefBean refBean3 () {
            return new RefBean3("bean 3");
        }
    
        public static class TestBean {
    
            // All bean instances of type RefBean will be injecting here
            @Autowired
            private Set<RefBean> refBeans;
                ...
        }
    
        public static class RefBean{
            private String str;
    
                public RefBean(String str){
                 this.str = str;
                }
             .....
        }
    }

    We can even inject a more general type i.e. interface or abstract class of same type but having different implementations.

    Note: If we want to inject above RefBean beans into a map then the resultant Map values will consist of all bean instances that match the expected type, and the Maps keys will contain the corresponding bean names.

    The injection point in above example:

                @Autowired
                private Map<String, RefBean> map; 

    Printing above map during runtime:

    {refBean1=RefBean{str='bean 1'}, refBean2=RefBean{str='bean 2'}, refBean3=RefBean{str='bean 3'}}


  5. Using @Qualifier for selection of array/collection/map elements:

    The JavaConfig factory methods (the ones annotated with @Bean) can expose themselves with a specific qualifying type using @Qualifier. In the tutorial Injecting Bean by name using @Qualifier, we used 'name' element of @Bean to be a specific qualifier for the injection points. The 'name' element is actually the bean id, which has to be unique per spring container. In collection case, we want to have more than one beans having same qualifier name, so that they can injected to a single collection having same qualifier. In that case we must use @Qualifier annotation along with @Bean instead of 'name' element.

    Let's modify above example to select only two beans using @Qualifier


    @Configuration
    public class SetInjection {
    
        @Bean
        public TestBean testBean () {
            return new TestBean();
        }
    
        @Bean
        public RefBean refBean1 () {
            return new RefBean("bean 1");
        }
    
        @Bean
        @Qualifier("myRefBean")
        public RefBean refBean2 () {
            return new RefBean2("bean 2");
        }
    
        @Bean
        @Qualifier("myRefBean")
        public RefBean refBean3 () {
            return new RefBean3("bean 3");
        }
    
        public static class TestBean {
    
            @Autowired
            @Qualifier("myRefBean")
            private Set<RefBean> refBeans;
                ...
        }
    }

    In above example only bean named refBean2 and refBean3 with be injected to the set in TestBean class.



  6. Ordering elements of arrays/list

    Beans can be ordered when they are injected into lists (not sets or map) or arrays. Both the @Order annotation and Ordered interface are supported. For example:

    @Configuration
    public class ArrayExample {
        @Bean
        public TestBean testBean () {
            return new TestBean();
        }
    
        @Bean
        @Order(3)
        public String refString1 () {
            return "my string 1";
        }
    
        @Bean
        @Order(1)
        public String refString2 () {
            return "my string 2";
        }
    
        @Bean
        @Order(2)
        public String refString3 () {
            return "my string 3";
        }
    
        private static class TestBean {
            private String[] stringArray;
    
            @Autowired
            public void setStringArray (String[] stringArray) {
                this.stringArray = stringArray;
            }
    
            public String[] getStringArray () {
                return stringArray;
            }
        }
    }

    stringArray in above example will be ordered as:

    [my string 2, my string 3, my string 1]

    In our example project below there's an Ordered interface usage as well.



  7. Using ComponentScan:

    With all above scenarios, we can also inject the beans using Component Scan approach. The example project includes many examples with those approaches as well.




To summarize important points:


Example Project

Dependencies and Technologies Used :

  • Spring Context 4.3.2.RELEASE: Spring Context.
  • JDK 1.8
  • Maven 3.0.4

Injecting Collections Example Select All Download
  • spring-collection-injection
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • array
                  • jconfig
                  • xml
                • collection
                  • jconfig
                  • xml
                • map
                  • jconfig
                  • xml
        • resources

See Also