为什么在我已经使用 @Produces 注释时会出现 "Ambiguous dependencies for interface" 异常?
Why do I get an "Ambiguous dependencies for interface" Exception when I'm already uses the @Produces annotation?
我在我的项目中使用了两个面向消息传递的中间件。 RabbitMQ 和 Apache Kafka。我有一个由 ConsumerRabbitMQ 和 ConsumerKafka 实现的消费者接口 IConsume。在启动时遇到一些情况,我使用 @Produces 注释为我将注入的接口 Bean 选择一个实现,但它给了我这个错误。
异常 1:
org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type IConsume with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject private com.mycompany.chatapp.startup.RunConsumers.ct
at com.mycompany.chatapp.startup.RunConsumers.ct(RunConsumers.java:0)
Possible dependencies:
- Session bean [class com.mycompany.chatapp.messagegateway.ConsumerRabbitMQ with qualifiers [@Any @Default]; local interfaces are [IConsume],
- Producer Method [IConsume] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces public com.mycompany.chatapp.startup.MOMConfigBean.produceIConsume()],
- Session bean [class com.mycompany.chatapp.messagegateway.ConsumerKafka with qualifiers [@Any @Default]; local interfaces are [IConsume]
@Default 和@Alternative 有效,但我希望它通过检查哪个中间件来选择运行。
查找有效,我也尝试了 beanName。我认为问题出在@Produces 上,但我找不到似乎是什么。
import javax.enterprise.inject.Produces;
@Singleton
@Startup
public class MOMConfigBean {
private String mom;
@PostConstruct
public void init() {
mom = "Kafka";
}
@EJB(lookup = "java:global/Chatapp/ConsumerKafka!com.mycompany.chatapp.messagegateway.IConsume")
IConsume kafkaConsumer;
@EJB(lookup = "java:global/Chatapp/ConsumerRabbitMQ!com.mycompany.chatapp.messagegateway.IConsume")
IConsume rabbitConsumer;
@Produces
public IConsume produceIConsume() {
if ("Kafka".equals(mom)) {
return kafkaConsumer;
} else {
return rabbitConsumer;
}
}
public interface IConsume {
// some code
}
@Stateless
public class ConsumerKafka implements IConsume{
// some code
}
@Stateless
public class ConsumerRabbitMQ implements IConsume {
// some code
}
public class runConsumers{
@Inject
private IConsume ct;
}
您有三个不明确的 IConsume
实例来源:
- 一个
ConsumerKafka
EJB
- 一个
ConsumerRabbitMQ
EJB
- 一种
@Produces public IConsume produceIConsume()
方法。
您需要使用限定符来消除 IConsume
实例的来源歧义。
这个限定符看起来像:
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD})
public @interface ConditionalMom {
}
那么制作人资格:
@Produces
@ConditionalMom
public IConsume produceIConsume() {
if ("Kafka".equals(mom)) {
return kafkaConsumer;
} else {
return rabbitConsumer;
}
}
和注射部位:
public class runConsumers{
@Inject
@ConditionalMom
private IConsume ct;
}
现在您拥有 @ConditionalMom IConsume
个实例的单一来源,因此它不再是模棱两可的。
您会发现,在您开始进一步利用 CDI 功能时,您将到处使用限定符。
我在我的项目中使用了两个面向消息传递的中间件。 RabbitMQ 和 Apache Kafka。我有一个由 ConsumerRabbitMQ 和 ConsumerKafka 实现的消费者接口 IConsume。在启动时遇到一些情况,我使用 @Produces 注释为我将注入的接口 Bean 选择一个实现,但它给了我这个错误。
异常 1:
org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type IConsume with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject private com.mycompany.chatapp.startup.RunConsumers.ct
at com.mycompany.chatapp.startup.RunConsumers.ct(RunConsumers.java:0)
Possible dependencies:
- Session bean [class com.mycompany.chatapp.messagegateway.ConsumerRabbitMQ with qualifiers [@Any @Default]; local interfaces are [IConsume],
- Producer Method [IConsume] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces public com.mycompany.chatapp.startup.MOMConfigBean.produceIConsume()],
- Session bean [class com.mycompany.chatapp.messagegateway.ConsumerKafka with qualifiers [@Any @Default]; local interfaces are [IConsume]
@Default 和@Alternative 有效,但我希望它通过检查哪个中间件来选择运行。
查找有效,我也尝试了 beanName。我认为问题出在@Produces 上,但我找不到似乎是什么。
import javax.enterprise.inject.Produces;
@Singleton
@Startup
public class MOMConfigBean {
private String mom;
@PostConstruct
public void init() {
mom = "Kafka";
}
@EJB(lookup = "java:global/Chatapp/ConsumerKafka!com.mycompany.chatapp.messagegateway.IConsume")
IConsume kafkaConsumer;
@EJB(lookup = "java:global/Chatapp/ConsumerRabbitMQ!com.mycompany.chatapp.messagegateway.IConsume")
IConsume rabbitConsumer;
@Produces
public IConsume produceIConsume() {
if ("Kafka".equals(mom)) {
return kafkaConsumer;
} else {
return rabbitConsumer;
}
}
public interface IConsume {
// some code
}
@Stateless
public class ConsumerKafka implements IConsume{
// some code
}
@Stateless
public class ConsumerRabbitMQ implements IConsume {
// some code
}
public class runConsumers{
@Inject
private IConsume ct;
}
您有三个不明确的 IConsume
实例来源:
- 一个
ConsumerKafka
EJB - 一个
ConsumerRabbitMQ
EJB - 一种
@Produces public IConsume produceIConsume()
方法。
您需要使用限定符来消除 IConsume
实例的来源歧义。
这个限定符看起来像:
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD})
public @interface ConditionalMom {
}
那么制作人资格:
@Produces
@ConditionalMom
public IConsume produceIConsume() {
if ("Kafka".equals(mom)) {
return kafkaConsumer;
} else {
return rabbitConsumer;
}
}
和注射部位:
public class runConsumers{
@Inject
@ConditionalMom
private IConsume ct;
}
现在您拥有 @ConditionalMom IConsume
个实例的单一来源,因此它不再是模棱两可的。
您会发现,在您开始进一步利用 CDI 功能时,您将到处使用限定符。