java 为什么Spring会将Map自动连接到另一个 Package 的Map中?

htrmnn0y  于 2023-04-19  发布在  Java
关注(0)|答案(1)|浏览(98)

我有下面的bean定义

@Bean(name="producerConfig")
public Map<String, Object> producerConfig() {

和以下注入声明

@Service
@Component("...)
public class DataAssetSnapshotPublisherLive {
    public SnapshotPublisherLive(..., @Qualifier("producerConfig") Map<String, Object> producerConfig) {
        ...
    }

我希望producerPublisher将被注入到producerPublisher变量中,因为它具有相同的类型和限定符。
我在调试器中看到的不是这个,而是它被 Package 了

producerConfig = {LinkedHashMap@12556}  size = 1
 "producerConfig" -> {HashMap@12561}  size = 27
  key = "producerConfig"
  value = {HashMap@12561}  size = 27

也就是说,producerConfig被新的HashMap初始化,并且一个元素被添加到哈希Map中。
为什么以及如何防止这种情况?

umuewwlo

umuewwlo1#

这是一个例子的干预“ Spring 魔术”在意想不到的方式。
在这种情况下,map autowiring工作:如果你注入一个Map<String, SomeClass>,那么Spring会把它看作一个特例。你想注入所有覆盖SomeClass的注册bean。
自动装配数组、集合和Map对于数组、集合或Map依赖类型,容器自动装配所有与声明的值类型匹配的bean。为此,Map键必须声明为String类型,该类型将被解析为相应的bean名称。这样的容器提供的集合将被排序,考虑目标组件的Ordered和@Order值,或者,单个匹配的目标bean也可以是一个一般类型的Collection或Map本身,以这种方式注入。
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/annotation/Autowired.html
因此,从本质上讲,您在调试器(即LinkedHashMap)中获得的是所有bean的列表:

  • 实现map声明中指定的类型(在本例中是Object,很多东西都实现了它)
  • 匹配限定符“producerConfig”(在本例中,只有一个匹配的bean,因此LinkedHashMap中只有1个条目)。

这些bean伴随着bean名称并按注册顺序排序,因此是LinkedHashMap。
请注意,如果map的key类型不是String,则不会发生这种情况。如果将Map<String, Object>替换为Map<Integer, Object>,则行为将完全不同,并且您将像最初期望的那样只获得单个bean注入。
关于“如何预防”:我不确定这个行为是否可以关闭,文档中没有任何说明。我认为最合理的解决方案是创建一个 Package 器类并注入它,而不是直接注入Map。

相关问题