首页 > 解决方案 > 在 Spring 中注入多个冲突的依赖项

问题描述

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

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

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

  1. FortuneService_RESTful
  2. 财富服务_随机

在我的 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 在幕后是如何工作的,这是一种简单明了的好奇心。

标签: javaspringdependency-injectioninversion-of-control

解决方案


好的,伙计们,我花了一天时间才看到这一点,但我可以确认这里发生的事情确实是随机的!

昨天,我只看到 method_ONE 胜出。今天,我看到 method_TWO 胜出。因此,我可以得出结论,Spring的注入顺序确实是随机的!

Thomas Klager 在上面的评论中提供了一个可以解释这种现象的建议:

[为此] 一个明显的原因是,使用基于注解的注入,spring 需要使用Class.getDeclaredMethods() or列出类的方法Class.getMethods()。这些方法都不会以任何特定的顺序返回方法。

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

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


推荐阅读