Java 使用CDI动态加载bean-EJB3

Java 使用CDI动态加载bean-EJB3,java,ejb-3.0,jndi,cdi,Java,Ejb 3.0,Jndi,Cdi,我在我的应用程序中使用EJB3,我想知道我能否基于一些参数在运行时动态地注入bean 因为我有一个@Local接口,它扩展了几个以不同方式工作的bean。因此,在运行时,我希望根据逻辑加载每个bean。到目前为止,我使用了常规的JNDI查找,但我想使用@Inject来完成它。有没有一种方法可以动态注入bean 这是我现有的查找代码。我在这里将bean名作为jndi传递,并动态构建实例 IService bean = (IService) initialContext.lookup(jndi+"B

我在我的应用程序中使用EJB3,我想知道我能否基于一些参数在运行时动态地
注入
bean

因为我有一个
@Local
接口,它扩展了几个以不同方式工作的bean。因此,在运行时,我希望根据逻辑加载每个bean。到目前为止,我使用了常规的
JNDI查找
,但我想使用
@Inject
来完成它。有没有一种方法可以动态注入bean

这是我现有的
查找
代码。我在这里将bean名作为
jndi
传递,并动态构建实例

IService bean = (IService) initialContext.lookup(jndi+"Bean/local"); 
bean.initializeTimer(firstDate, period, request);

更新 我现在有三颗豆子
第一个bean是SingleServiceBean

 @Stateless
 public class SingleServiceBean implements IService{

    @Override
    public void doSomething (){
     log.debug("inside do something");
    }

    private final Log log = LogFactory.getLog(SingleServiceBean.class.getName());
 }
第二个bean是PeriodicService

 @Stateless
 public class PeriodicServiceBean implements IService{

    @Override
    public void doSomething (){
     log.debug("inside do something");
    }

    private final Log log = LogFactory.getLog(PeriodicServiceBean.class.getName());
 }
三豆

 @Stateless
 public class AsyncServiceBean implements IService{

    @Override
    public void doSomething (){
     log.debug("inside do something");
    }

    private final Log log = LogFactory.getLog(AsyncServiceBean.class.getName());
 }

第二次更新 限定符:

 @Qualifier
 @Target({ TYPE, METHOD, PARAMETER, FIELD })
 @Retention(RUNTIME)
 @Documented
 public @interface Services {
   String type(); 

 }
注释文字

 public class ServiceQualifier extends AnnotationLiteral<Services> implements Services{

private static final long serialVersionUID = 6471734834552932687L;
private String type;

public String TypeQualifier(String t) {
      this.type = t;
      return type;
}

public String type() {
    return type;
}
 }
然后我在我的bean调用者类中添加以下几行

 @Inject
private Instance<IService> iServiceInstance;

public void someMethod() {

// this line gives me error by red underline in .select(...)
IService service = iServiceInstance.select(new ServiceQualifier().TypeQualifier("SingleService")).get();
}
@Inject
私有实例;
公共方法(){
//这一行以红色下划线表示错误。选择(…)
IService service=iServiceInstance.select(新建ServiceQualifier().TypeQualifier(“SingleService”)).get();
}

eclipse中出现错误:“类型实例中的方法选择(注释…)不适用于参数(字符串)”

是firstdate、period和request运行时参数吗?如果是这样,您只能注入某种基于这些属性创建bean的工厂

如果这些值在部署时是固定的或至少是可配置的,您可以使用生产者

@Produces
public IService getTimer() {
  IService bean = (IService) initialContext.lookup(jndi+"Bean/local"); 
  bean.initializeTimer(firstDate, period, request);
  return bean;
}

您需要找到一种方法来提供配置值。检查限定符概念或使用System.set/get属性传输值。

是firstdate、period和request运行时参数吗?如果是这样,您只能注入某种基于这些属性创建bean的工厂

如果这些值在部署时是固定的或至少是可配置的,您可以使用生产者

@Produces
public IService getTimer() {
  IService bean = (IService) initialContext.lookup(jndi+"Bean/local"); 
  bean.initializeTimer(firstDate, period, request);
  return bean;
}

您需要找到一种方法来提供配置值。检查限定符概念或使用System.set/get属性传输值。

假设您使用的是本地接口,则需要在CDI(而不是JNDI位置)中使用限定符。在impl上,执行以下操作:

@Local
@Stateless
@MyQualifier("someValue")
public class MyServiceOne implements IService {
    ...
}
其中
MyQualifier
可以有任何值,甚至是JNDI名称。然后,如果要解决此问题,请执行以下操作:

@Inject @Any
private Instance<IService> iServiceInstance;

...

IService service = iServiceInstance.select(new MyQualifierLiteral("someValue")).get();

假设您使用的是本地接口,则需要在CDI(而不是JNDI位置)中使用限定符。在impl上,执行以下操作:

@Local
@Stateless
@MyQualifier("someValue")
public class MyServiceOne implements IService {
    ...
}
其中
MyQualifier
可以有任何值,甚至是JNDI名称。然后,如果要解决此问题,请执行以下操作:

@Inject @Any
private Instance<IService> iServiceInstance;

...

IService service = iServiceInstance.select(new MyQualifierLiteral("someValue")).get();

我不熟悉限定词,有点困惑。我已经更新了我所有的三个bean类,你能详细说明一下吗?我不知道还能怎么详细说明。如果你不清楚限定词,这个网站可能会有所帮助:我用你的答案更新代码。请参阅第二次更新。我得到一个错误“类型实例中的方法选择(注释…)不适用于参数(字符串)”。不知道我哪里错了。你能帮我一下吗,约翰?我哪里出错了?我更新了我的答案,介绍了如何定义注释文字。我不熟悉限定符,有点困惑。我已经更新了我所有的三个bean类,你能详细说明一下吗?我不知道还能怎么详细说明。如果你不清楚限定词,这个网站可能会有所帮助:我用你的答案更新代码。请参阅第二次更新。我得到一个错误“类型实例中的方法选择(注释…)不适用于参数(字符串)”。不知道我哪里错了。你能帮我一下吗,约翰?我哪里出错了?我更新了我的答案,介绍了如何定义注释文字。对不起,Jan,我想在这里使用CDI。所以不再进行上下文查找了。从您最初的帖子中,我假设您需要处理远程EJB。对不起,Jan,我想在这里使用CDI。所以不再进行上下文查找了。从您最初的帖子中,我假设您要处理远程EJB。方法“TypeQualifier”应该返回ServiceQualifier实例,因为.select(..)的参数必须是注释文字,而不是字符串。因此,替换为“返回此项;”并更改此方法的返回类型,所有操作都将正常进行。方法“TypeQualifier”应返回ServiceQualifier实例,因为.select(..)的参数必须是注释文字,而不是字符串。因此,替换为“返回此项;”并更改此方法的返回类型,所有操作都将正常工作。