【问题标题】:Is it possible to destroy a CDI scope?是否可以销毁 CDI 范围?
【发布时间】:2011-09-21 12:19:58
【问题描述】:

我正在开发一个 Java EE 应用程序,主要是带有 JSF 管理控制台的 JAX-RS,它使用 CDI/Weld 对 javax.enterprise.context.ApplicationScoped 对象进行依赖注入。除了一些小的调试问题,CDI 在这个项目中表现出色。

现在我需要对注入 CDI 的对象生命周期进行一些非常粗粒度的控制。我需要具备以下能力:

我完全清楚,这与 CDI 和依赖注入的本质相悖,如果不是反对的话。我只想知道

  • 这远程可行吗?
  • 如果是,完成工作的最简单/最简单/最快/最安全的方法是什么?

【问题讨论】:

  • 只是好奇:如果这些对象只是全局对象,即一些静态字段怎么办。不涉及 DI。在您的特定应用程序中,您能否证明 DI 对您的应用范围对象真的很有价值?
  • 这不会为这个应用程序飞行。我使用 DI 不仅仅是因为它有光泽。
  • 我认为这根本不违背 DI 的原则 - 毕竟,创建 CDI 规范是为了准确解决范围生命周期的问题,并明确允许创建新范围(已授予, 在上下文中重新创建特定的 bean 不是 CDI 方式)

标签: java jakarta-ee cdi jboss-weld


【解决方案1】:

开箱即用,只有 Conversation 范围可让您完全控制其生命周期。但是,如果对话不适合您的需要,您可以创建自己的范围。 创建范围是一项艰巨的工作,但您可以去焊接代码并查看对话是如何实现的。

【讨论】:

  • 我确实尝试过使用对话范围 - 不幸的是,我的短暂尝试没有成果。看起来自定义范围是唯一的解决方案,尽管我真的不想走这条路……
【解决方案2】:

焊接参考文档Section 2.1.2

请记住,一旦绑定了 bean 就上下文而言,它仍然存在于 上下文直到上下文是 被摧毁。没有办法手动 从上下文中删除一个 bean。如果你 不想让豆子坐在 会话无限期,考虑使用 另一个寿命较短的示波器, 例如请求或对话 范围。

自定义范围示例Porting the veiwscoped jsf annonation to cdi

如果您真的不想采用自定义范围类型的路径。您可以使用 non-portable 方法,使用 BeanManager.getContext 方法并将此上下文强制转换为焊缝 @ 987654324@ 可以访问 beanstore 或 context 的 cleanUp() 方法。

查看此线程,了解如何为您的环境获取 BeanManager 实例

【讨论】:

  • @Matt Ball 抱歉,没有看到您真的不想进入自定义范围类型,所以我编辑答案以添加我可以看到的另一个可能的解决方案。
  • 感谢您的信息!如果有机会,我一定会尝试这种(非便携式)方法。
【解决方案3】:

https://github.com/openknowledge/openknowledge-cdi-extensions/tree/master/openknowledge-cdi-scope/src/main/java/de/openknowledge/cdi/scope 提供了一个可能适合您需求的自定义范围,也许您需要稍微调整一下实现。

【讨论】:

  • 这可能会做得很好......我假设你是在专门谈论DestroyableContext
  • 是的。它至少非常相似。您还可以查看 MyFaces CODI 的以 JSF 为中心的范围,这些范围也是细粒度的,但如果您需要独立于 JSF 和/或易于用作自定义范围的模板,那可能适合。
【解决方案4】:

在 CDI 1.1 中有一个javax.enterprise.context.spi.AlterableContext 接口,它允许您单独销毁一个 bean 实例。所有正常范围(请求、对话、会话)都是可更改的。

AlterableContext ctxConversation = (AlterableContext) beanManager.getContext(ConversationScoped.class);
for (Bean<?> bean : beanManager.getBeans(Object.class)) {
    Object instance = ctxConversation.get(bean);
    if (instance != null) {
        ctxConversation.destroy(instance);
    }
}

这里的beanManager 是一个javax.enterprise.inject.spi.BeanManager 实例。您可以通过 JNDI 查找获得它:

InitialContext.doLookup("java:comp/BeanManager");

或通过 CDI 静态方法:

CDI.current().getBeanManager();

,但请注意某些 Weld 版本中静态方法的问题:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-30
    相关资源
    最近更新 更多