使用CDI动态加载Bean - EJB3

时间:2014-02-16 16:08:10

标签: java ejb-3.0 jndi cdi

我在我的应用程序中使用EJB3,并且我想知道我可以在运行时基于某些参数动态地inject bean吗?

因为我有一个@Local接口,它扩展了几个以不同方式工作的bean。所以在运行时我想根据逻辑加载每个bean。到目前为止,我常用JNDI lookup但是我想用@Inject来做。有没有办法可以动态地注入bean?

这是我现有的lookup代码。我在这里将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(); 

 }

AnnotationLiteral

 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类

 @Services(type = "SingleService" )
 @Stateless
 public class SingleServiceBean implements IService{
 .....
 }

然后我在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();
}

我在eclipse中遇到的错误:“Instance类型中的方法select(Annotation ...)不适用于参数(String)”

2 个答案:

答案 0 :(得分:4)

假设您正在使用本地接口,则需要在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();

MyQualifierLiteral这是AnnotationLiteral实施MyQualifier。这应该是它的样子:

import javax.enterprise.util.AnnotationLiteral;

public class MyQualifierLiteral extends AnnotationLiteral<MyQualifier> implements MyQualifier {

    private final String value;

    public MyQualifierLiteral(final String value) {
        this.value = value;
    }

    @Override
    public String value() {
        return this.value;
    }

}

答案 1 :(得分:0)

是firstdate,period和request runtime args吗?如果是这样,你只能注入某种基于这些属性创建bean的工厂。

如果这些值在部署时修复或至少可配置,则可以使用Producer。

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

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