在春季注入多个冲突的依赖项

时间:2018-08-06 16:39:26

标签: java spring dependency-injection inversion-of-control

我有一个Spring bean类,它要求注入依赖项。但是,在我的班级中,我手动将不同的依赖项连接到同一私有类变量。在这种情况下会发生什么?哪个注射先例?

详细信息:
我创建了一个名为BadmintonCoach的Spring bean类。

它依赖于IfortuneService帮助器。 IfortuneService是具有两个不同实现的接口。这两个实现是:

  1. FortuneService_RESTful
  2. FortuneService_Random

在我的badmintonCoach类中,我创建了一个私有变量来接收来自Spring的注入:

private IFortuneService theFortuneService

也就是说,我正在手动将注入的依赖项连接到该私有成员theFortuneService

我正在使用方法注入来注入这些iFortuneService依赖项。

这是问题所在:我有两个方法,这两个方法都要求Spring注入iFortuneService类型的方法。一个方法请求一个实现(FortuneService_RESTful),另一个方法请求另一个实现的Bean(FortuneService_Random)。

这两种方法都将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是 prototyped 的,该怎么办?显然,将为每个请求创建一个新的化身,并且仅分配给我的BadmintonCoach类一个助手类。但是哪个化身会胜出?

如果可以使我的问题更清楚,我可以提供全部代码。

如果您想知道为什么我编写了冲突代码?试图了解Spring在幕后的工作方式是一种简单而简单的好奇心。

1 个答案:

答案 0 :(得分:0)

好吧,我花了一天的时间看这个,但我可以确认这里发生的事情确实是随机!

昨天,我完全看到method_ONE获胜。今天,我看到method_TWO获胜。因此,我可以得出结论,春季注射顺序确实是随机的!

托马斯·克拉格(Thomas Klager)在上面的评论中提供了一个建议,可以解释这种现象:

  

一个明显的原因[为此]是使用基于注释的注入   需要使用Class.getDeclaredMethods()列出类的方法   或Class.getMethods()。这些方法均未返回中的方法   任何特定的订单。

我仍然发现,由Spring执行相同逻辑(即Class.getDeclaredMethods()Class.getMethods())如何产生这样的随机结果仍然是一个谜。

了解此限制非常重要!编写代码时,您可能会发现自己想使用注入依赖项的服务,而这些依赖项又依赖于其他注入依赖项的服务。从该实验中可以明显看出,这可能很危险,因此您不应以这种方式分层布线。也就是说,如果布线跨越多种方法,则布线应始终为单层,否则,可能会冒着程序虚假输出的风险。可以在Slim在link中的回答中看到这种危险的说明。