您现在的位置是:首页 > 文章详情

Spring 注入 Bean 到 List / Map 中

日期:2019-05-26点击:424

前言

由于在工作中遇到了这样的问题,所以随笔写下来,记录一下。
我们平常习惯的注入方式是:
@Autowired
private 类的名称 对象名称;
这种方式是最简单的,也是最实用的。但是有些时候我们就需要将实现了同样接口的Bean注入到Context中,然后可以用 List / Map 接受注入的对象。

正文

想象一下这样的例子,我们需要解析一个字符串,有好几个解析这个字符串的Service,然后在对赢得地方使用对应的Service。如果我们把每一个解析器Service都有一个自己的接口,那么就违背了,他们都在做同一件事,只是做法不同的初衷。如果是有默认解析器,可以使用@Primary注解(这个注解会在实现相同接口的Bean中找到有@Primary,把这个Bean作为优先级最高的注入进来),如果有好多个@Primary, Spring 又会傻傻分不清,到底要注入那个,于是就会报Exception,这个时候我们可以使用@Qualifier具体指定以哪个实体类注入。如果这样的话,当我们在一个地方需要好多个解析器,我们得写好多个@Autowired以及具体指定的@Qualifier。
Spring的厉害之处,就是咱们的烦恼,他都能想得到,于是便有了将注入的Bean 放在List或者Map中这样的 “玩法”。
下面直接上例子:
我创建了一个接口叫做“Parent”然后有三个实现它的类分别为 “ChildA”,“ChildB”,“ChildC”。然后创建了一个Controller类,用于注入那些Bean。目录结构如下:
屏幕快照 2019-01-26 下午10.02.48.png
Parent 类代码如下:

package com.example.injectdemo.model; public interface Parent { public void say(); } 

Child类代码如下:

package com.example.injectdemo.model; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component("ChildA") public class ChildA implements Parent{ @Override public void say() { System.out.println("I am ChildA"); } } 

Tips:@Component一定要传递这个bean注入的名称,因为在这个时候spring不会自动帮我们把注入的bean的名称处理好。
Controller类代码如下:

package com.example.injectdemo; import com.example.injectdemo.model.Parent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import java.util.List; import java.util.Map; import java.util.Set; @Controller @RequestMapping("/test") public class InjectController { @Autowired private Map<String, Parent> map; @Autowired private List<Parent> list; @RequestMapping("/say") public void sayTest(){ Set<Map.Entry<String, Parent>> sets = map.entrySet(); for(Map.Entry<String,Parent> item:sets){ System.out.println(item.getKey()); } for(Parent parent : list){ parent.say(); } } }

Tips:Map的Key是实现类的名称,Value为具体的类(Value的泛型为接口名称)
启动Application后,访问URL,查看结果,结果为:

ChildA ChildB ChildC I am ChildA I am childB I am ChildC

Map我在这里不多说,通过代码,可以看的一清二楚。
List我在多说一点:
如果我们不想让调用的顺序为ChildA->ChildB->ChildC怎么办。
我们可以分别在这三个实现的@Component注解下面加上@Order(number),这里的number 可以填写数字。数字越大,在list中越靠前。
加完之后 ChildA是这样的:

package com.example.injectdemo.model; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component("ChildA") @Order(3) public class ChildA implements Parent{ @Override public void say() { System.out.println("I am ChildA"); } }

其他的B,C分别加上 2和1
输出的顺序是:
ChildA
ChildB
ChildC
I am ChildC
I am childB
I am ChildA

原文链接:https://yq.aliyun.com/articles/703751
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章