Spring – Injecting Collections – Spring – 注入集合

最后修改: 2018年 6月 7日

中文/混合/英文(键盘快捷键:t)

 

1. Introduction

1.介绍

In this tutorial, we’re going to show how to inject Java collections using the Spring framework.

在本教程中,我们将展示如何使用Spring框架注入Java集合

Simply put, we’ll demonstrate examples with the List, Map, Set collection interfaces.

简单地说,我们将演示使用List、Map、Set集合接口的例子。

2. List With @Autowired

2.List@Autowired

Let’s create an example bean:

让我们创建一个bean的例子。

public class CollectionsBean {

    @Autowired
    private List<String> nameList;

    public void printNameList() {
        System.out.println(nameList);
    }
}

Here, we declared the nameList property to hold a List of String values.

在这里,我们声明了nameList属性来保存ListString值。

In this example, we use field injection for nameList. Therefore, we put the @Autowired annotation.

在这个例子中,我们对nameList使用字段注入。因此,我们放置了@Autowired 注解

To learn more about the dependency injection or different ways to implement it, check out this guide.

要了解有关依赖注入的更多信息或实现依赖注入的不同方法,请查看此指南

After, we register the CollectionsBean in the configuration setup class:

之后,我们在配置设置类中注册CollectionsBean

@Configuration
public class CollectionConfig {

    @Bean
    public CollectionsBean getCollectionsBean() {
        return new CollectionsBean();
    }

    @Bean
    public List<String> nameList() {
        return Arrays.asList("John", "Adam", "Harry");
    }
}

Besides registering the CollectionsBean, we also inject a new list by explicitly initializing and returning it as a separate @Bean configuration.

除了注册CollectionsBean,我们还通过显式初始化并将其作为一个单独的@Bean配置返回来注入一个新的列表。

Now, we can test the results:

现在,我们可以测试一下结果。

ApplicationContext context = new AnnotationConfigApplicationContext(CollectionConfig.class);
CollectionsBean collectionsBean = context.getBean(
  CollectionsBean.class);
collectionsBean.printNameList();

The output of printNameList() method:

printNameList()方法的输出。

[John, Adam, Harry]

3. Set With Constructor Injection

3.使用构造函数注入的Set

To set up the same example with the Set collection, let’s modify the CollectionsBean class:

为了用Set集合设置同样的例子,我们来修改CollectionsBean类。

public class CollectionsBean {

    private Set<String> nameSet;

    public CollectionsBean(Set<String> strings) {
        this.nameSet = strings;
    }

    public void printNameSet() {
        System.out.println(nameSet);
    }
}

This time we want to use a constructor injection for initializing the nameSet property. This requires also changes in configuration class:

这次我们想使用构造函数注入来初始化nameSet属性。这也需要对配置类进行修改。

@Bean
public CollectionsBean getCollectionsBean() {
    return new CollectionsBean(new HashSet<>(Arrays.asList("John", "Adam", "Harry")));
}

4. Map With Setter Injection

4.带有setter注入的Map

Following the same logic, let’s add the nameMap field to demonstrate the map injection:

按照同样的逻辑,让我们添加 nameMap字段来演示地图注入。

public class CollectionsBean {

    private Map<Integer, String> nameMap;

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

    public void printNameMap() {
        System.out.println(nameMap);
    }
}

This time we have a setter method in order to use a setter dependency injection. We also need to add the Map initializing code in configuration class:

这次我们有一个setter方法,以便使用setter依赖性注入。我们还需要在配置类中添加Map初始化代码。

@Bean
public Map<Integer, String> nameMap(){
    Map<Integer, String>  nameMap = new HashMap<>();
    nameMap.put(1, "John");
    nameMap.put(2, "Adam");
    nameMap.put(3, "Harry");
    return nameMap;
}

The results after invoking the printNameMap() method:

调用printNameMap()方法后的结果。

{1=John, 2=Adam, 3=Harry}

5. Injecting Bean References

5.注入Bean引用

Let’s look at an example where we inject bean references as elements of the collection.

让我们看看一个例子,在这个例子中,我们将bean引用作为集合的元素注入。

First, let’s create the bean:

首先,让我们来创建Bean。

public class BaeldungBean {

    private String name;

    // constructor
}

And add a List of BaeldungBean as a property to the CollectionsBean class:

并添加一个ListBaeldungBean作为CollectionsBean类的一个属性。

public class CollectionsBean {

    @Autowired(required = false)
    private List<BaeldungBean> beanList;

    public void printBeanList() {
        System.out.println(beanList);
    }
}

Next, we add the Java configuration factory methods for each BaeldungBean element:

接下来,我们为每个BaeldungBean元素添加Java配置工厂方法。

@Configuration
public class CollectionConfig {

    @Bean
    public BaeldungBean getElement() {
        return new BaeldungBean("John");
    }

    @Bean
    public BaeldungBean getAnotherElement() {
        return new BaeldungBean("Adam");
    }

    @Bean
    public BaeldungBean getOneMoreElement() {
        return new BaeldungBean("Harry");
    }

    // other factory methods
}

The Spring container injects the individual beans of the BaeldungBean type into one collection.

Spring容器将BaeldungBean类型的各个Bean注入一个集合中。

To test this, we invoke the collectionsBean.printBeanList() method. The output shows the bean names as list elements:

为了测试这一点,我们调用了collectionsBean.printBeanList()方法。输出显示了作为列表元素的Bean名称。

[John, Harry, Adam]

Now, let’s consider a scenario when there is not a BaeldungBean. If there isn’t a BaeldungBean registered in the application context, Spring will throw an exception because the required dependency is missing.

现在,让我们考虑一下没有BaeldungBean时的情况。如果应用程序上下文中没有注册BaeldungBean,Spring将抛出一个异常,因为缺少所需的依赖。

We can use @Autowired(required = false) to mark the dependency as optional. Instead of throwing an exception, the beanList won’t be initialized and its value will stay null.

我们可以使用@Autowired(required = false)来标记该依赖关系为可选。而不是抛出一个异常,beanList将不会被初始化,其值将保持null

If we need an empty list instead of null, we can initialize beanList with a new ArrayList:

如果我们需要一个空列表而不是null,我们可以用一个新的ArrayList>初始化beanList

@Autowired(required = false)
private List<BaeldungBean> beanList = new ArrayList<>();

5.1. Using @Order to Sort Beans

5.1.使用@Order对Bean进行排序

We can specify the order of the beans while injecting into the collection.

我们可以在注入集合时指定bean的顺序

For that purpose, we use the @Order annotation and specify the index:

为此,我们使用@Order注解并指定索引。

@Configuration
public class CollectionConfig {

    @Bean
    @Order(2)
    public BaeldungBean getElement() {
        return new BaeldungBean("John");
    }

    @Bean
    @Order(3)
    public BaeldungBean getAnotherElement() {
        return new BaeldungBean("Adam");
    }

    @Bean
    @Order(1)
    public BaeldungBean getOneMoreElement() {
        return new BaeldungBean("Harry");
    }
}

Spring container first will inject the bean with the name “Harry”, as it has the lowest order value.

Spring容器首先将注入名称为“Harry”的bean,因为它的订单值最低。

It will then inject the “John”, and finally, the “Adam” bean:

然后它将注入“John”,最后是“Adam”Bean。

[Harry, John, Adam]

Learn more about @Order in this guide.

在此指南中了解更多关于@Order的信息。

5.2. Using @Qualifier to Select Beans

5.2.使用@Qualifier来选择bean

We can use the @Qualifier to select the beans to be injected into the specific collection that matches the @Qualifier name.

我们可以使用@Qualifier来选择要注入到符合@Qualifier名称的特定集合中的bean。

Here’s how we use it for the injection point:

下面是我们如何将其用于注射点。

@Autowired
@Qualifier("CollectionsBean")
private List<BaeldungBean> beanList;

Then, we mark with the same @Qualifier the beans that we want to inject into the List:

然后,我们用同样的@Qualifier标记我们想要注入List的bean。

@Configuration
public class CollectionConfig {

    @Bean
    @Qualifier("CollectionsBean")
    public BaeldungBean getElement() {
        return new BaeldungBean("John");
    }

    @Bean
    public BaeldungBean getAnotherElement() {
        return new BaeldungBean("Adam");
    }

    @Bean
    public BaeldungBean getOneMoreElement() {
        return new BaeldungBean("Harry");
    }

    // other factory methods
}

In this example, we specify that the bean with the name “John” will be injected into the List named “CollectionsBean”. The results we test here:

在这个例子中,我们指定名称为“John”的Bean将被注入名为“CollectionsBean”List中。我们在这里测试的结果。

ApplicationContext context = new AnnotationConfigApplicationContext(CollectionConfig.class);
CollectionsBean collectionsBean = context.getBean(CollectionsBean.class);
collectionsBean.printBeanList();

From the output, we see that our collection has only one element:

从输出中,我们看到我们的集合只有一个元素。

[John]

6. Setting an Empty List as a Default Value

6.将一个空列表设置为默认值

We can set the default value for an injected List property as an empty list by using the Collections.emptyList() static method:

我们可以通过使用Collections.emptyList()静态方法为注入的List属性设置默认值为空列表。

public class CollectionsBean {

    @Value("${names.list:}#{T(java.util.Collections).emptyList()}")
    private List<String> nameListWithDefaultValue;
    
    public void printNameListWithDefaults() {
        System.out.println(nameListWithDefaultValue);
    }
}

If we run this with the “names.list” key not initialized via properties file:

如果我们在 “names.list “键没有通过属性文件初始化的情况下运行这个程序。

collectionsBean.printNameListWithDefaults();

We’ll get an empty list as output:

我们会得到一个空列表作为输出。

[ ]

7. Summary

7.总结

With this guide, we learned how to inject different types of Java collections using the Spring framework.

通过本指南,我们学习了如何使用Spring框架注入不同类型的Java集合。

We also examined injection with reference types and how to select or order them inside of the collection.

我们还研究了参考类型的注入,以及如何在集合中选择或排列它们。

As usual, the complete code is available in the GitHub project.

像往常一样,完整的代码可以在GitHub项目中获得。