我在我的应用程序中使用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)”
答案 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属性传输值。