如何使用相同的@Qualifier注入bean列表?

时间:2016-08-18 18:24:17

标签: java spring

这是我的代码:

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

import javax.annotation.Resource;
import java.util.List;

@Configuration
public class ResourceTest {

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

    @Bean
    TargetBean targetBean () {
        return new TargetBean("bean1");
    }

    @Bean(name = "myBean")
    TargetBean targetBean2 () {
        return new TargetBean("bean2");
    }

    @Bean(name = "myBean")
    TargetBean targetBean3 () {
        return new TargetBean("bean3");
    }

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

    }

    public static class TestBean {
        private List<TargetBean> targetBeanList;

        @Resource(name = "myBean")
        public void setXList (List<TargetBean> targetBeanList) {
            this.targetBeanList = targetBeanList;
        }

        public List<TargetBean> getTargetBeanList () {
            return targetBeanList;
        }
    }

    public static class TargetBean {
        private final String str;

        public TargetBean (String str) {
            this.str = str;
        }

        public String getStr () {
            return str;
        }

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

输出: [TargetBean {str ='bean2'}]

预期: 符合“myBean”的所有bean都应该在列表中,即bean2和bean3。

根据spring ref docs:

  

限定符也适用于类型化集合,如上所述,例如,Set。在这种情况下,根据声明的限定符的所有匹配bean都作为集合注入。这意味着限定符不必是唯一的;它们只是简单地构成过滤标准。例如,您可以使用相同的限定符值“action”定义多个MovieCatalog bean,所有这些bean都将注入到使用@Qualifier(“action”)注释的Set中。

我正在使用Spring 4.3.2.RELEASE。请帮忙解决这个问题。提前谢谢。

2 个答案:

答案 0 :(得分:4)

name带注释的元素中的@Bean表示相应的bean定义的标识符。如果您有两个具有相同ID的bean定义,则稍后注册的bean将覆盖前一个。这就是你的豆子在这里发生的事情

@Bean(name = "myBean")
TargetBean targetBean2 () {
    return new TargetBean("bean2");
}

@Bean(name = "myBean")
TargetBean targetBean3 () {
    return new TargetBean("bean3");
}

您已将该部分文档链接起来,但您没有做过它所说的任何事情。

  

例如,您可以使用。定义多个MovieCatalog bean   相同的限定符值&#34;动作&#34;

让我们适应你的豆子

@Bean(name = "myBean2")
@Qualifier("myBean")
TargetBean targetBean2() {
    return new TargetBean("bean2");
}

@Bean(name = "myBean3")
@Qualifier("myBean")
TargetBean targetBean3() {
    return new TargetBean("bean3");
}

请注意,它们具有不同的ID(您可以省略@Bean注释,而Spring将使用方法名称)但使用相同的@Qualifier值。

然后

  

所有这些都将被注入带有@Qualifier("action")

注释的集合中

在注射点,使用

@Autowired
@Qualifier("myBean")
public void setXList(List<TargetBean> targetBeanList) {
    this.targetBeanList = targetBeanList;
}

targetBeanList现在将包含符合TargetBean条件的两个myBean bean。

Spring使用提供的@Resource解析name来查找bean的名称。它不了解@Qualifier值。这就是我们将@Autowired@Qualifier一起使用的原因。

答案 1 :(得分:0)

感谢Sotirios Delimanolis帮助我解决问题。

总结我的理解:

(1)&#39;名称&#39; @Bean中的元素(name = ....)是标识符而不是限定符。它可能与匹配限定符(我们使用@Autowired以及@Qualifier或@Resource的注入点)一起使用,但在我的情况下不能,因为id不能声明为相同。

(2)使用@Qualifier注释声明true限定符,该注释可与@Bean方法,@ Component(类)以及@Autowired(注入点)一起使用。

我想,当谈到通过某种名称匹配/过滤bean时,我们应该总是使用@Qualifier,即从不依赖于(1)。

顺便说一下,我想对上述回复发表评论..但由于某些原因,它不接受......;)