什么时候@Dependent范围的CDI bean被销毁,如果你通过Provider.get()获得那个bean?

Chr*_*kin 10 java-ee cdi jboss-weld weld

我很难理解@DependentCDI 1.0和CDI 1.1中作用域的有效生命周期.到目前为止,我的实验得出了以下结论:

  • 一个@Dependent作用域的bean没有代理.
  • @PreDestroy@Dependentbean被销毁时,不会调用任何方法.
  • Provider.get()总是创建一个@Dependentbean 的新实例.
  • 使用JBoss 6/CDI 1.0,@Dependent@ApplicationScopedbean的Provider<>字段创建的bean 被"泄露",因为它仍然"属于" Provider.
  • 在使用WELD 2.1.2.Final/CDI 1.1时,我没有看到@Dependent类似Providers 泄漏豆类的证据(还有!).(虽然这可能是因为这些特定的 @Dependent bean是由@Produces方法创建的......!)

我看到CDI 1.1已添加了一种destroy()方法Instance<>,可能是为了解决CDI 1.0中的内存泄漏问题.但那怎么样Provider<>- CDI 1.1中是否还会泄漏?(如果确实如此,那么你应该怎么用Provider.get()?)

基本上,我有几个@ApplicationScopedbean/@SingletonEJB,我@Inject Provider试图Provider.get()用作两者的工厂@Dependent@RequestScoped"帮助"bean.我绝对希望这些bean"属于"他们的Provider字段,因为我需要将bean随后进行垃圾收集:

public void updateStuff() {
    Helper helper = helperProvider.get();
    // use helper...
}
Run Code Online (Sandbox Code Playgroud)

对于我的CDI 1.0应用程序,我正在考虑通过Provider使用以下代码"伪造"来修复内存泄漏:

provider = new Provider<MyBean>() {
    @Override
    public MyBean get() {
        return getReferenceFor(MyBean.class);
    }
};

private <T> T getReferenceFor(Class<T> type) {
    Bean<?> bean = beanManager.resolve(beanManager.getBeans(type));
    CreationalContext<?> context = beanManager.createCreationalContext(bean);
    try {
        return (T) beanManager.getReference(bean, bean.getBeanClass(), context);
    } finally {
        // Destroy this context - which I don't want to exist anyway.
        // I only need a strong reference to a fully @Inject-ed bean!
        context.release();
    }
}
Run Code Online (Sandbox Code Playgroud)

MyBean是一个@Dependentscoped bean,没有@PreDestroy方法,只有在我完成它时才需要进行垃圾回收.但是,我找不到很多关于Providers 的信息,因此无法判断我是否通过这样做来武装某种定时炸弹.

我的一些@Dependentscoped bean(我仍然通过Provider.get()btw 获得)是由@Produces方法创建的.他们还有被泄露的危险吗?

有人可以告诉我吗?
谢谢,
克里斯

Yur*_*uri 3

来自关于 @Dependent beans 生命周期的Weld 文档:

依赖 bean 的实例永远不会在不同客户端或不同注入点之间共享。它严格来说是某个其他对象的依赖对象。当它所属的对象被创建时它被实例化,当它所属的对象被销毁时它被销毁。

因此,@Dependent 对象的注入本身不会引入泄漏,根本没有什么需要修复的。仅仅“为了安全起见”创建一个短暂的上下文是完全没有必要的,因为依赖 bean 不与上下文绑定。就注入后的 CDI 而言,它们是普通(强可达)Java 对象。
如果您需要实例化逻辑,请将其放入生产者方法中,仅此而已。

  • 顺便说一句,根据 [CDI 文档](http://docs.jboss.org/cdi/api/1.0-SP1/javax/enterprise/context/Dependent.html):“获得了范围为 @Dependent 的 bean 实例通过直接调用 Instance 是 Instance 实例的依赖对象。” 因此,它比“普通的强可达 Java 对象”稍微多一些——它与其创建者绑定在一起!我正在尝试用我的解决方法代码撤消这种绑定。 (2认同)