zoukankan      html  css  js  c++  java
  • 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();
            }
        }
    }
  • 相关阅读:
    PythonのTkinter基本原理
    使用 Word (VBA) 分割长图到多页
    如何使用 Shebang Line (Python 虚拟环境)
    将常用的 VBScript 脚本放到任务栏 (Pin VBScript to Taskbar)
    关于 VBScript 中的 CreateObject
    Windows Scripting Host (WSH) 是什么?
    Component Object Model (COM) 是什么?
    IOS 打开中文 html 文件,显示乱码的问题
    科技发展时间线(Technology Timeline)
    列置换密码
  • 原文地址:https://www.cnblogs.com/myseries/p/13453146.html
Copyright © 2011-2022 走看看