4

是否有可能以CDI conversation编程方式获取一个实例,只知道当前thread是用于处理CDI request与所需对话相关联的实例?如果可能的话怎么办?

特别是,我想做的是:

@ConversationScoped
public class UnitOfWork {...}

public class Client {
    @Inject transient UnitOfWork uof;
...
}

public class Room {
    @Inject transient UnitOfWork uof;
...
}

但是使用编程机制来初始化uof实例变量而不是应用 @Inject 注释(因为ClientRoom是实体并且它们不支持注入)。 我已经尝试通过以下静态方法获得的
注入:UnitOfWorkBeanManager

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);
    }
}

但问题是通过上述方法给出的bean是新的(每次调用都会给出一个新实例),我需要它ClientRoom共享相同的会话范围实例UnitOfWork

4

2 回答 2

2

抱歉,这不是一个真正的答案,但在评论中写得太多了:

实体不支持依赖注入是有原因的——主要是因为它们的生命周期与托管 bean 的生命周期是分离的。

虽然我当然在实体中看到了 DI 的用例,但我会加倍(和三倍)检查这种方法的好处是否超过风险。您可能会发现自己在某种二级缓存地狱中破解了持久性上下文;)

于 2012-09-05T09:19:56.293 回答
1

答案非常接近,但我忽略了它。是的,可以通过 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 类实例以避免内存泄漏。在这里,我解释了如何很好地做到这一点。

于 2013-02-06T01:58:27.153 回答