java - 在 Spring 中注入多个冲突的依赖项
问题描述
我有一个 Spring bean 类,它请求注入依赖项。但是,在我的班级中,我手动将不同的依赖项连接到同一个私有类变量。在这种情况下会发生什么?哪个注射先例?
详细信息:
我创建了一个名为 BadmintonCoach 的 Spring bean 类。
它依赖于一个 IfortuneService 助手。IfortuneService 是一个具有两种不同实现的接口。这两个实现是:
- FortuneService_RESTful
- 财富服务_随机
在我的 badmintonCoach 类中,我创建了一个私有变量来接收来自 Spring 的注入:
private IFortuneService theFortuneService
也就是说,我手动将注入的依赖连接到这个私有成员,theFortuneService
我正在使用方法注入注入这些 iFortuneService 依赖项。
但问题是:我有两种方法,这两种方法都请求从 iFortuneService 类型的 Spring 进行注入。一种方法请求一个实现 (FortuneService_RESTful),而另一种方法请求另一个实现 (FortuneService_Random) 的 bean。
这两种方法都设置this.theFortuneService
为等于其各自请求的帮助器。所以我在 BadmintonCoach 课上的内容是:
private IFortuneService theFortuneService
@Autowired
@Qualifier("fortuneService_Random")
public void randomMethod_ONE(IFortuneService theFortuneService) {
System.out.println("Code inside randomMethod_ONE!");
this.theFortuneService = theFortuneService;
}
@Autowired
@Qualifier("fortuneService_RESTful")
public void randomMethod_TWO(IFortuneService theFortuneService) {
System.out.println("Code inside randomMethod_TWO!");
this.theFortuneService = theFortuneService;
}
那么我的问题是:
两条线路中的哪一条胜出?为什么?Spring 如何决定其注入的顺序?什么决定了注射的顺序?是随机的吗?它是按方法名称的字母顺序注入的吗?构造函数、setter、字段和方法注入之间是否有注入顺序?
当我运行我的程序时,我看到了什么?我看到fortuneService_RESTful 的注入胜出,但我不清楚这是偶然的还是Spring 逻辑中的设计。
这里有另一个想法:
如果上面的两个方法没有请求 IFortuneService 接口的不同实现,而是请求同一个 bean,但该 bean 是原型的,该怎么办?显然,将为每个请求创建一个新的化身,并且只有一个助手类分配给我的 BadmintonCoach 类。但是哪个化身会赢呢?
如果它能让我的问题更清楚,我可以提供我的整个代码。
如果您想知道为什么我编写了相互冲突的代码?尝试了解 Spring 在幕后是如何工作的,这是一种简单明了的好奇心。
解决方案
好的,伙计们,我花了一天时间才看到这一点,但我可以确认这里发生的事情确实是随机的!
昨天,我只看到 method_ONE 胜出。今天,我看到 method_TWO 胜出。因此,我可以得出结论,Spring的注入顺序确实是随机的!
Thomas Klager 在上面的评论中提供了一个可以解释这种现象的建议:
[为此] 一个明显的原因是,使用基于注解的注入,spring 需要使用
Class.getDeclaredMethods()
or列出类的方法Class.getMethods()
。这些方法都不会以任何特定的顺序返回方法。
我仍然觉得 Spring 执行相同逻辑(即:Class.getDeclaredMethods()
或Class.getMethods()
)如何产生这样的随机结果是个谜。
了解此限制非常重要!在编写代码时,您可能会发现自己想要使用注入依赖项的服务,而这些服务又依赖于其他注入依赖项的服务。从这个实验中可以清楚地看出,这可能是危险的,因此您不应该以这种方式分层布线。也就是说,如果跨越多个方法,您的连线应该始终是单层的,否则,您将面临程序产生虚假输出的风险。可以在 Slim 在此链接中的回答中看到这种危险的说明。
推荐阅读
- asp.net - 我可以在我的 asp.net mvc 核心中的根站点的 url 中添加一个静态名称吗
- javascript - React 明确不要在 html 中渲染组件
- .net-core - DOTNET_ROOT Not Recognised After Raspbian Reboot
- regex - RegEx to match all sets of items that have part of specific value
- xamarin.forms - Xamarin Forms SFDataGrid 绑定问题
- python - 使用python计算一维数组和nD数组之间的距离
- javascript - APIRTC 离开对话不允许重新进入
- java - 无法更改snackBar 中的变量值
- ios - 如何使用 SwiftUI 使 MKScaleView 在初始地图加载时正确显示
- bash - 递归查找和复制特定的 mimetype 文件