模棱两可的自动装配,但 none 带有限定符

Ambiguous autowiring but none with qualifier

我有一个服务,它注入一个 Bean@Autowired 如下。

@Service
public class AdminServiceImpl implements AdminService {
    @Autowired
    private WebServiceTemplate adminServiceTemplate;
}

还有一个包含两个 bean 的 xml,导致不明确的自动装配

<bean id="serviceWebClient" class="org.springframework.ws.client.core.WebServiceTemplate" scope="prototype">
    <constructor-arg ref="messageFactory" />
    <property name="marshaller" ref="marshaller" />
<!-- More properties -->
</bean>

<bean id="adminServiceWebClient" class="org.springframework.ws.client.core.WebServiceTemplate" scope="prototype">
    <constructor-arg ref="messageFactory" />
    <property name="marshaller" ref="marshaller" />
<!-- More properties -->
</bean>

这显然会导致以下异常(启动时)

No qualifying bean of type [org.springframework.ws.client.core.WebServiceTemplate] is defined: expected single matching bean but found 2: serviceWebClient,adminServiceWebClient

奇怪的部分:

当我在我的服务中添加 @Qualifier 以指定 Bean 到 select 时,它突然找不到了。例如。我将我的服务编辑为以下内容:

@Service
public class AdminServiceImpl implements AdminService {
    @Autowired
    @Qualifier("adminServiceWebClient")
    private WebServiceTemplate adminServiceTemplate;
}

我没有得到我指定的 Bean,而是收到以下异常消息 (稍后当我用 context = new ClassPathXmlApplicationContext(CONFIG_FILE); 检索 ApplicationContext 时):

 No qualifying bean of type [org.springframework.ws.client.core.WebServiceTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.

对发生这种奇怪的事情有什么合乎逻辑的解释吗?我什至不确定从哪里开始调试。好像两个都找到了,但还是不肯autowire一个。

编辑

从我的 XML@Qualifier 注释中删除额外的 Bean 时,我 仍然 得到:

 No qualifying bean of type [org.springframework.ws.client.core.WebServiceTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.

但它在启动时运行良好。调用后失败:

context = new ClassPathXmlApplicationContext(CONFIG_FILE);

所以在启动时它似乎找到了它(它是必需的并且不会失败),但是在请求上下文时它失败了。

也许您实际上正在启动两个应用程序上下文?一个会有那些豆子,而另一个不会。

如果是这种情况,当存在限定符时,您的第一个上下文将正常启动,但第二个上下文将由于缺少 bean 而失败(异常 #2)。如果没有限定符,第一个上下文将由于两个替代项而无法启动。

要解决这个问题(当启动第二个上下文时)给它一个父上下文:

new ClassPathXmlApplicationContext(new String[]{CONFIG_LOCATION}, parentContext);

我找到了为什么会出现这个问题。这是一个(相当愚蠢的)错误。如果其他人也 运行 对此感兴趣,请查看以下内容:

概述

我 运行 我的应用程序有各种 Spring Bean 文件。当我的应用程序启动时,我使用 "main context" 文件对我的整个基础包执行 component-scan。在这个 "main" 文件中,我有 WebServiceTemplate Beans.

启动

我的 component-scan 找到我的 service 并自动将其尊重的 WebServiceTemplate Bean 连接到其中。所以它在启动时工作正常,正如预期的那样。

运行时间

当我打电话时

context = new ClassPathXmlApplicationContext(CONFIG_FILE);

我实际上调用了一个不同的文件。该文件包含WebServiceTemplate Beans,但确实还包含整个基础包的component-scan。导致它找到我的 Service,但找不到它应该自动装配的 bean。

解决方案

加载其他文件时,我将 component-scan 更改为缩小到我需要的范围。所以它不会扫描服务,但会在启动时加载。