Spring原型bean-prototype不能销毁? 转载

一个原型bean的例子:

 

结果是 注解的@PreDestroy的方法close()没有执行,而如果是单例bean 的singleton则会执行

 

那若想销毁Spring的原型bean应该怎么办呢?

看这篇分析: java – 需要手动销毁Spring原型bean吗?

 

我注意到我的原型范围的Spring bean的@PreDestroy钩子没有被执行.

我已经读过here,这实际上是设计的. Spring容器将销毁单例bean,但不会销毁原型bean.我不清楚为什么.如果Spring容器将创建我的原型bean并执行其@PostConstruct钩子,为什么在容器关闭时它也不会破坏我的bean?一旦我的Spring容器关闭,继续使用它的任何bean都有意义吗?我看不到你想要在完成bean之前关闭容器的场景.甚至可以在容器关闭后继续使用原型Spring bean吗?

上面描述了我的主要问题的令人费解的背景:如果Spring容器没有破坏原型bean,那是否意味着可能发生内存泄漏?或者原型bean会在某些时候被垃圾收集?

春季文件指出:

 

The client code must clean up prototype-scoped objects and release
expensive resources that the prototype bean(s) are holding. To get the
Spring container to release resources held by prototype-scoped beans,
try using a custom bean post-processor, which holds a reference to
beans that need to be cleaned up.

那是什么意思?该文本告诉我,我作为程序员负责明确(手动)销毁我的原型bean.它是否正确?如果是这样,我该怎么做?

 

最佳答案
为了他人的利益,我将在下面介绍我从调查中收集到的内容:

只要原型bean本身不持有对另一个资源(如数据库连接或会话对象)的引用,只要删除了对该对象的所有引用或对象超出范围,就会立即收集垃圾.因此,通常没有必要显式销毁原型bean.

但是,在如上所述可能发生内存泄漏的情况下,可以通过创建单一bean后处理器来销毁原型bean,其后处理方法显式调用原型bean的销毁挂钩.因为后处理器本身是单例范围的,所以Spring会调用它的破坏钩子:

> 创建一个bean post处理器来处理所有原型bean的销毁.这是必要的,因为Spring不会破坏原型bean,因此代码中的任何@PreDestroy挂钩永远不会被容器调用.
> 实现以下接口:

1.BeanFactoryAware
  该接口提供了一个接收Beanfactory对象的回调方法.此BeanFactory对象在后处理器类中用于通过其BeanFactory.isPrototype(String beanName)方法标识所有原型bean.

2. DisposableBean
  此接口提供Spring容器调用的Destroy()回调方法.我们将在此方法中调用所有原型bean的Destroy()方法.

3. BeanPostProcessor
  实现此接口提供对进程内回调的访问,我们在其中准备内部List<> Spring容器实例化的所有原型对象.我们稍后将遍历此List<>销毁我们的每个原型bean.

4.最后在每个原型bean中实现DisposableBean接口,提供此契约所需的Destroy()方法.

为了说明这个逻辑,我提供了以下从article中获取的一些代码:

/**
* Bean PostProcessor that handles destruction of prototype beans
*/
@Component
public class DestroyPrototypeBeansPostProcessor implements BeanPostProcessor, BeanFactoryAware, DisposableBean {

    private BeanFactory beanFactory;

    private final List<Object> prototypeBeans = new LinkedList<>();

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanFactory.isPrototype(beanName)) {
            synchronized (prototypeBeans) {
                prototypeBeans.add(bean);
            }
        }
        return bean;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void destroy() throws Exception {
        synchronized (prototypeBeans) {
            for (Object bean : prototypeBeans) {
                if (bean instanceof DisposableBean) {
                    DisposableBean disposable = (DisposableBean)bean;
                    try {
                        disposable.destroy();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            prototypeBeans.clear();
        }
    }
}

 

posted @ 2020-08-07 15:25  myseries  阅读(2692)  评论(0编辑  收藏  举报