Close

Spring Framework - Injecting Map Examples

Spring Framework 

Constructor based map injection: The map is passed directly to the TestBean constructor in the configuration class.
Please see the proxied methods using CGLIB. of configuration class.

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

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class MapInjectionExample {
@Bean
public TestBean testBean () {
HashMap<String, Integer> map = new HashMap<>();
map.put("one", 1);
map.put("two", 2);
return new TestBean(map);
}

public static void main (String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(
MapInjectionExample.class);
TestBean bean = context.getBean(TestBean.class);
System.out.println(bean.getMap());
}

private static class TestBean {
private final Map<String, Integer> map;
//@Autowired not required anymore, starting Spring 4.3
private TestBean (Map<String, Integer> map) {
this.map = map;
}

public Map<String, Integer> getMap () {
return map;
}
}
}




Setter based map injection: The map instance is registered to the Spring container itself so it can be used at multiple places but as a singleton instance.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class MapInjectionPropExample {

@Bean
public TestBean testBean () {
return new TestBean();
}

@Bean
public Map<String, Integer> map () {
HashMap<String, Integer> map = new HashMap<>();
map.put("one", 1);
map.put("two", 2);
return map;
}

public static void main (String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(
MapInjectionPropExample.class);
TestBean bean = context.getBean(TestBean.class);
System.out.println(bean.getMap());
}

private static class TestBean {
private Map<String, Integer> map;

@Autowired
public void setMap (Map<String, Integer> map) {
this.map = map;
}

public Map<String, Integer> getMap () {
return map;
}
}
}




Injecting maps based on matching type: In this example multiple instances of the same type are registered as beans. The setter injection point TestBean#setMap (Map<String, RefBean> map) is injected based on type. If we replace the Map with a single instance of RefBean in the setter, there will be NoUniqueBeanDefinitionException.
It's also important to understand that RefBean will be injected as value of the map and the keys will be the bean name, which are, in our example, the same as config method name (refBean and refBean2).

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

@Configuration
public class MapRefInjection {

@Bean
public TestBean testBean () {
return new TestBean();
}

@Bean
public RefBean refBean () {
return new RefBean("one");
}

@Bean
public RefBean refBean2 () {
return new RefBean("two");
}


public static void main (String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(MapRefInjection.class);
TestBean bean = context.getBean(TestBean.class);
System.out.println(bean.getMap());
}

private static class TestBean {
private Map<String, RefBean> map;

/**
* An autowired Maps values will consist of all bean instances that match the expected
* type, and the Maps keys will contain the corresponding bean names.
*/
@Autowired
public void setMap (Map<String, RefBean> map) {
this.map = map;
}

public Map<String, RefBean> getMap () {
return map;
}
}

private static class RefBean {
private final String str;

private RefBean (String str) {
this.str = str;
}

@Override
public String toString () {
return "RefBean{" +
"str='" + str + '\'' +
'}';
}
}
}




Component scanning and injecting map based on generic type and qualifier

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Map;

@Configuration
@ComponentScan(basePackageClasses = MapRefInjectionQualifierScan.class,
useDefaultFilters = false,
includeFilters = @ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
value = {MapRefInjectionQualifierScan.class}))
public class MapRefInjectionQualifierScan {


public static void main (String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(
MapRefInjectionQualifierScan.class);
TestBean bean = context.getBean(TestBean.class);
System.out.println(bean.getMap());
}

@Component
private static class TestBean {
private Map<String, RefBeanService> map;

@Autowired
@Qualifier("myMapRef")
public void setMap (Map<String, RefBeanService> map) {
this.map = map;
}

public Map<String, RefBeanService> getMap () {
return map;
}
}

private static abstract class RefBeanService {
public abstract String getStr ();

@Override
public String toString () {
return "RefBean{str='" + getStr() + "'}";
}

}

@Component("bean name 1")
@Qualifier("myMapRef")
private static class RefBean extends RefBeanService {

@Override
public String getStr () {
return "one";
}
}

@Component("bean name 2")
private static class RefBean2 extends RefBeanService {

@Override
public String getStr () {
return "two";
}
}

@Component("bean name 3")
@Qualifier("myMapRef")
private static class RefBean3 extends RefBeanService {

@Override
public String getStr () {
return "three";
}
}
}




See Also