【发布时间】:2012-01-13 04:27:57
【问题描述】:
我们开始尝试使用 CDI 实现我们的后端服务。场景是这样的:
带有@Startup 的EJB 在EAR 部署时启动。一个 ApplicationScoped bean 被注入到这里:
@ApplicationScoped
public class JobPlatform {
private PooledExecutor threadHolder;
@Inject @Any
private Instance<Worker> workerSource;
...
该 bean 还有一个 Observer 方法,当观察到一个事件时,它会从 Instance workerSource 中获取一个工作 bean 并将其放在 threadPool 中,并最终运行到完成。
一切运行良好。然而......我们已经开始看到垃圾收集问题。 JMAP 堆直方图显示有许多这样的工人在闲逛,没有收集垃圾。
我们认为这要归功于 CDI 范围界定的组合。 @Dependant (http://docs.jboss.org/cdi/api/1.0-SP1/javax/enterprise/context/Dependent.html) 的 API 页面更清楚地强化了文档中的内容:
- 注入到字段、bean 构造函数或初始化方法中的具有 @Dependent 范围的 bean 实例是注入它的 bean 或 Java EE 组件类实例的依赖对象。
- 注入到生产者方法中的具有 @Dependent 范围的 bean 实例是正在生成的生产者方法 bean 实例的依赖对象。
- 通过直接调用Instance获得的作用域为@Dependent的bean实例是Instance实例的依赖对象。
所以,接下来:
- workerSource bean 绑定到 JobPlatform,因此具有 ApplicationScoped 生命周期
- 使用该实例检索的任何工作 bean 都绑定到它,因此具有 ApplicationScoped 生命周期
- 因为 ApplicationScoped 上下文的 beanstore(我对术语的了解在这里有点模糊)仍然引用了工作 bean,所以它们不会被销毁/垃圾收集
使用 CDI 的人是否同意这一点?您是否遇到过这种缺乏垃圾收集的情况,如果有,您能提出任何解决方法吗?
worker 不能是 ApplicationScoped,但平台必须是。如果我们要创建一个自定义的 WorkerScope(呃哦……)并用它来注解每个 worker 类,这是否足以分离 worker 和实例源之间的依赖关系?
Is it possible to destroy a CDI scope? 也有一些建议,我会看看,但希望对范围界定是否是一个正当理由提供一些支持。
希望你能帮忙,谢谢。
【问题讨论】:
标签: garbage-collection scope cdi jboss-weld