【问题标题】:Weld Ambiguous dependency with @Alternative使用@Alternative 焊接不明确的依赖项
【发布时间】:2015-10-23 11:24:57
【问题描述】:

我的一个课程中有一个注入点

@Inject
private UsbServices usbServices;

还有一个带有 @Produces 方法的 Weld 类

public class AppProducer
{

    @Produces
    @Singleton
    public UsbServices getUsbServices()
    {
        UsbServices usbServices = null;
        try
        {
            usbServices = UsbHostManager.getUsbServices();
        } catch (SecurityException | UsbException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return usbServices;
    }

}

我希望在集成测试期间更换替代实现,所以我有上述类的替代版本

@Alternative
public class TestAppProducer
{

    @Produces
    @Singleton
    public UsbServices getUsbServices()
    {
        return new UsbServicesSimulator();
    }

}

以及测试包resources/META-INF里面我的beans.xml中的以下内容

<beans xmlns="http://java.sun.com/xml/ns/javaee" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
      http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
      <alternatives>
          <class>xxx.TestAppProducer</class>
      </alternatives>
</beans>

为了测试这一点,我试图用它的主类启动 Weld 并手动连接一个 USB“设备”。测试方法如下

Weld weld = new Weld();
WeldContainer container = weld.initialize();
PCSyncApplication app = container.instance().select(PCSyncApplication.class).get();
ServicesManager servMan = app.getServicesManager();
UsbServicesSimulator servSimulator = (UsbServicesSimulator) servMan.getUsbServices();
servSimualtor.attachDevice(new FakeDevice());

但是我得到一个模棱两可的依赖异常

Exception in thread "main" org.jboss.weld.exceptions.DeploymentException: Exception List with 2 exceptions:
Exception 0 :
org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type UsbServices with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject private xxx.manager.ServicesManager.usbServices
  at xxx.manager.ServicesManager.usbServices(ServicesManager.java:0)
  Possible dependencies: 
  - Managed Bean [class xxx.simulator.usb.UsbServicesSimulator] with qualifiers [@Any @Default],
  - Producer Method [UsbServices] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces @Singleton public xxx.AppProducer.getUsbServices()]

编辑:如果我用以下信息注释 UsbServicesSimulator,则小更新会消失

@Alternative
public class UsbServicesSimulator implements UsbServices

但我不完全确定我理解为什么。我会认为beans.xmlTestAppProducer&lt;alternatives&gt; 部分就足够了吗?

【问题讨论】:

  • 实际上你的错误表明UsbServices已经是一个托管bean。你应该@Veto它,这样它就不会自己生成任何bean定义。
  • UsbHostManager.getUsbServices()提供的UsbServices的实现是第三方类所以无法注释
  • 您使用的是什么容器(包括版本)?
  • 我正在使用 Weld Java SE 2.3.0.Final

标签: java cdi weld


【解决方案1】:

使用@Alternative 注释,您只能禁用您的测试服务,但不能解决模棱两可的依赖关系。如果你想启用你的替代,主版本不应该在类路径中可见或应该具有较低的优先级,例如。使用 beans.xml 或 @Vetoed 注释或禁用 @Priority。 还有一些其他的技巧,
你可以在这里找到完整的文档https://docs.jboss.org/weld/reference/latest/en-US/html/injection.html#alternatives

我更喜欢使用单独的项目,或者使用 Arquillian 运行测试,并且在类路径中只有我需要的那个类。 在这种情况下,我不建议使用优先级。因为您需要为您的生产版本禁用或设置较低的优先级。

【讨论】:

    猜你喜欢
    • 2020-01-09
    • 1970-01-01
    • 2020-08-09
    • 2016-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-18
    • 2013-04-07
    相关资源
    最近更新 更多