随笔 - 832  文章 - 2  评论 - 31  阅读 - 167万

Spring注解的(List&Map)特殊注入功能 (源码没有看)

一、先看一个示例演示:spring注解的一个特殊的注入功能。

首先,是定义一个接口,3个实现类。

复制代码
复制代码
public interface GreetService {

    public String sayHello(String name);
    
}
@Service("china")
public class ChinaGreetServiceImpl implements GreetService {

    @Override
    public String sayHello(String name) {
        return "你好";
    }

}
@Service("japan")
public class JapanGreetServiceImpl implements GreetService {

    @Override
    public String sayHello(String name) {
        return "亚麻得";
    }

}
@Service("usa")
public class UsaGreetServiceImpl2 implements GreetService {

    @Override
    public String sayHello(String name) {
        return "hello";
    }

}
复制代码
复制代码

下面看到代码中有直接注入一个List和一个Map的。示例代码如下:

GreetController代码:

复制代码
复制代码
@RestController
@RequestMapping("/greet")
public class GreetController {

    @Autowired
    private List<GreetService> greetServiceList;

    @Autowired
    private Map<String, GreetService> greetServiceMap;

    @RequestMapping(value = "/test/{id}", method = RequestMethod.GET)
    public String getbook5(@ApiParam("id编号") @PathVariable("id") Long id) {
        for (Map.Entry<String, GreetService> entry : greetServiceMap.entrySet()) {
            System.out.println(entry.getValue().sayHello("" + id));
        }
        System.out.println("==list====");
        for (GreetService greetService : greetServiceList) {
            System.out.println(greetService.sayHello("" + id));
        }

        return "" + id;
    }

}
复制代码
复制代码

最后在调试List的时候突然灵感一闪,如果只有一个对象那么List里面的值不就只有一个吗。于是开始测试验证,结果发现的确如此。当实例化一个GreetController之后,另外一个类采用泛型注入List,Spring竟然成功的将实例化的对象放入List之中。思路打开之后,针对Map的就更好说了。Spring会将service的名字作为key,对象作为value封装进入Map。@Order    可以指定顺序

运行之后,访问http://127.0.0.1:8091/greet/test/1执行结果如下:

原来,在不知不觉中Spring已经帮我们做了很多事情,只是我们不知道而已。

 二、@Autowired 注入集合类型

从spring-beans-4.3.14.RELEASE.jar的源码可以看看到如下:

在org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DependencyDescriptor, String, Set<String>, TypeConverter) 方法中发现了原因。

对于@Autowired声明的数组、集合类型,spring并不是根据beanName去找容器中对应的bean,而是把容器中所有类型与集合(数组)中元素类型相同的bean构造出一个对应集合,注入到目标bean中。对应到上问配置文件中,就是把容器中所有类型为java.lang.String的bean放到新建的Set中,然后注入到Manager bean中。也就是把resourcePackage和resourceLoaction这两个String注入了,导致上面的输出结果。

在spring reference中也发现相关说明。

@Autowired

If you intend to express annotation-driven injection by name, do not primarily use @Autowired, even if is technically capable of referring to a bean name through @Qualifier values. Instead, use the JSR-250 @Resource annotation, which is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process.
As a specific consequence of this semantic difference, beans that are themselves defined as a collection or map type cannot be injected through @Autowired, because type matching is not properly applicable to them. Use @Resource for such beans, referring to the specific collection or map bean by unique name.
@Autowired applies to fields, constructors, and multi-argument methods, allowing for narrowing through qualifier annotations at the parameter level. By contrast, @Resource is supported only for fields and bean property setter methods with a single argument. As a consequence, stick with qualifiers if your injection target is a constructor or a multi-argument method.

从上面的说明中找到解决办法就是注入集合类型不要使用@Autowired,而使用@Resource注解。同时Spring官方也是不推荐使用@Autowired的。

posted on   小破孩楼主  阅读(423)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示