Java 没有为注入创建接口的 EE bean

Java EE bean with interface not being created for injection

我有一个简单的案例,我有一个 REST 服务 MyService,应该注入一个 BeanB 类型的 bean beanB,它实现了接口 BeanBInterface。我得到的错误是 classic WELD-001408 如下所示:

org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type BeanBInterface with qualifiers @BeanBQualifier
  at injection point [BackedAnnotatedField] @Inject @BeanBQualifier public com.example.MyService.beanB
  at com.example.MyService.beanB(MyService.java:0)

REST 服务:

import javax.ws.rs.Path;
import javax.inject.Inject;

@Path("/")
public class MyService {
    @Inject 
    @BeanBQualifier(BeanBQualifier.Type.PROD)
    public BeanBInterface beanB;

    public MyService() {}
}

Bean 接口:

public interface BeanBInterface {
}

Bean 实现:

import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.enterprise.inject.Produces;

@Startup
@Singleton
@BeanBQualifier(BeanBQualifier.Type.PROD)
public class BeanB implements BeanBInterface {
    private String name = "B";

    public BeanB() {}

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}
}

Bean 限定词

import javax.inject.Qualifier;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE})
public @interface BeanBQualifier {
   Type value();
   enum Type{PROD, TEST}
}

Beans.xml(在 META-INF/beans.xml 中尝试过,也在 WEB-INF/beans.xml 中尝试过)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee  http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"

    bean-discovery-mode="annotated">
</beans>

我也试过 bean-discovery-mode="all" 但没有成功。

如果我将 beanB 声明为使用具体的 class BeanB 而不是它在 MyService 中的接口,它就可以工作(但这违背了界面):

如果我向 MyService 添加一个 @Produces 工厂方法来构建 bean,它也可以工作,但这违背了让容器为我实例化我的 bean 的目的:

@javax.enterprise.inject.Produces
public static BeanB get() {
    return new BeanB();
}

但是如果这个@Produces 工厂方法returns 接口将不起作用:

@javax.enterprise.inject.Produces
public static BeanBInterface get() {
    return new BeanB();
}

EJB 有一些关于哪些接口实际公开为实现的奇怪规则。只有标记为@Local/@Remote 的接口才会被公开。如果要将 bean 与接口和 class 一起使用,则需要将 @LocalBean 添加到 ejb。

简而言之:在接口中添加@Local或在BeanB中添加@Local(BeanBInterface.class)