Spring Framework Tutorial

Software Setup and Configuration (STS/Eclipse/IntelliJ)

Core Spring

Spring Annotations

Spring Data

Spring JDBC

Spring Security

Spring - Constructor Injection with Collection

Constructor injection in Spring is used to inject dependencies through a class's constructor. If the dependency is a collection, such as a List, Set, or Map, Spring offers specific elements for XML configuration and constructs for Java-based configuration.

Let's look at an example of how you can inject a collection through constructor injection.

1. XML Configuration:

Let's say we have an Library class that depends on a List of Book objects.

Book.java:

public class Book {
    private String title;

    public Book(String title) {
        this.title = title;
    }

    // getters, setters, etc.
}

Library.java:

import java.util.List;

public class Library {
    private List<Book> books;

    public Library(List<Book> books) {
        this.books = books;
    }

    // getters, setters, etc.
}

spring-config.xml:

<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="book1" class="com.example.Book">
        <constructor-arg value="Harry Potter" />
    </bean>

    <bean id="book2" class="com.example.Book">
        <constructor-arg value="The Lord of the Rings" />
    </bean>

    <bean id="library" class="com.example.Library">
        <constructor-arg>
            <list>
                <ref bean="book1" />
                <ref bean="book2" />
            </list>
        </constructor-arg>
    </bean>

</beans>

Here, we defined two Book beans and injected them into the Library bean using a list.

2. Java-based Configuration:

Let's achieve the same using Java-based configuration:

LibraryConfig.java:

package com.example;

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

import java.util.Arrays;
import java.util.List;

@Configuration
public class LibraryConfig {
    
    @Bean
    public Book book1() {
        return new Book("Harry Potter");
    }

    @Bean
    public Book book2() {
        return new Book("The Lord of the Rings");
    }

    @Bean
    public Library library() {
        return new Library(Arrays.asList(book1(), book2()));
    }
}

Here, we're defining our beans using the @Bean annotation and assembling our Library bean with a list of books.

3. Autowiring with Annotations:

If you're using component scanning and annotation-based configuration, you can use @Autowired for constructor injection:

Library.java (Updated):

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class Library {
    private List<Book> books;

    @Autowired
    public Library(List<Book> books) {
        this.books = books;
    }

    // getters, setters, etc.
}

Here, the Library bean expects a list of Book beans to be available in the application context and will get them injected automatically.

  1. Constructor injection with List or Set in Spring framework:

    • Use List or Set in constructor injection for injecting a collection of dependencies.
    // MyService.java
    import java.util.List;
    
    public class MyService {
    
        private final List<MyDependency> dependencies;
    
        public MyService(List<MyDependency> dependencies) {
            this.dependencies = dependencies;
        }
    }
    
  2. Injecting Map in Spring constructor using annotations:

    • Inject a Map in the constructor using annotations for key-value pairs.
    // MyService.java
    import java.util.Map;
    
    public class MyService {
    
        private final Map<String, MyDependency> dependenciesMap;
    
        public MyService(Map<String, MyDependency> dependenciesMap) {
            this.dependenciesMap = dependenciesMap;
        }
    }
    
  3. Spring constructor injection with array or ArrayList example:

    • Demonstrate constructor injection with an array or ArrayList.
    // MyService.java
    import java.util.ArrayList;
    
    public class MyService {
    
        private final String[] stringArray;
    
        public MyService(String[] stringArray) {
            this.stringArray = stringArray;
        }
    
        // OR
    
        private final ArrayList<MyDependency> dependencyList;
    
        public MyService(ArrayList<MyDependency> dependencyList) {
            this.dependencyList = dependencyList;
        }
    }
    
  4. How to pass a collection to a constructor in Spring:

    • Pass a collection to a constructor by configuring the dependencies in the Spring configuration.
    // AppConfig.java
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.List;
    
    @Configuration
    public class AppConfig {
    
        @Bean
        public MyService myService(List<MyDependency> dependencies) {
            return new MyService(dependencies);
        }
    
        // Other configuration...
    }
    
  5. Constructor-based dependency injection with collections in Spring:

    • Configure constructor-based dependency injection in Spring using collections.
    // AppConfig.java
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.List;
    
    @Configuration
    public class AppConfig {
    
        @Bean
        public MyService myService(List<MyDependency> dependencies) {
            return new MyService(dependencies);
        }
    
        // Other configuration...
    }
    
  6. Injecting a collection of objects using Spring IoC container:

    • Use the Spring IoC container to inject a collection of objects into the constructor.
    // AppConfig.java
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.Set;
    
    @Configuration
    public class AppConfig {
    
        @Bean
        public MyService myService(Set<MyDependency> dependencies) {
            return new MyService(dependencies);
        }
    
        // Other configuration...
    }