仅仅知道当前thread是用来处理与所需对话相关联的CDI request的那个the,就可以通过编程获得一个CDI conversation实例吗?如果可能,那么如何实现呢?
特别是,我想要做的是:
@ConversationScoped
public class UnitOfWork {...}
public class Client {
@Inject transient UnitOfWork uof;
...
}
public class Room {
@Inject transient UnitOfWork uof;
...
}但是使用编程机制来初始化uof实例变量,而不是应用@Inject注释(因为Client和Room是实体,它们不支持注入)。
我已经尝试通过以下静态方法获得的BeanManager注入UnitOfWork:
public static <B> B getManagedBean(Class<B> type, Annotation... qualifiers) {
try {
BeanManager beanManager = InitialContext.doLookup("java:comp/BeanManager");
Set<Bean<?>> beans = beanManager.getBeans(type, qualifiers);
Bean<B> bean = (Bean<B>) beanManager.resolve(beans);
CreationalContext<B> cc = beanManager.createCreationalContext(bean);
return bean.create(cc);
} catch (NamingException e) {
throw new RuntimeException("", e);
}
}但问题是,通过上述方法提供的UnitOfWork是新的(每次调用都会提供一个新的实例),并且我需要Client和bean共享相同的会话范围的bean实例。
发布于 2013-02-06 09:58:27
答案很接近,但我忽略了它。是的,可以通过BeanManager获得任何活动上下文(与当前线程相关联的上下文)所包含的任何bean的bean类实例。此方法完成以下工作:
public static <B> B getContextualBeanInstance(Class<B> type, Annotation... qualifiers) {
try {
BeanManager beanManager = InitialContext.doLookup("java:comp/BeanManager");
Set<Bean<?>> beans = beanManager.getBeans(type, qualifiers);
Bean<?> bean = beanManager.resolve(beans);
CreationalContext<?> cc = beanManager.createCreationalContext(bean);
return (B) beanManager.getReference(bean, type, cc);
} catch (NamingException e) {
throw new RuntimeException("", e);
}
}与我在问题帖子中提到的方法唯一的区别是,这个方法使用的是BeanManager#getReference(..)而不是Bean#create(..)。
如果希望支持参数化bean类型,请将type参数的类型从Class<B>更改为Type。
如果bean的作用域是@Dependent,那么您应该注意bean类实例的销毁,以避免内存泄漏。Here,我会解释如何很好地做到这一点。
发布于 2012-09-05 17:19:56
抱歉,不是真正的答案,但太多了,无法在评论中写出来:
实体不支持依赖注入的原因有很多,主要是因为它们的生命周期与托管beans的生命周期解耦。
虽然我肯定在实体中看到了依赖注入的用例,但我会加倍(和三倍)检查这种方法的好处是否大于风险。您可能会发现自己在某种二级缓存地狱中破解持久性上下文;)
https://stackoverflow.com/questions/12257006
复制相似问题