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();
            }
        }
    }
  • 相关阅读:
    直击JDD | 京东技术全景图首次展示 四大重磅智能技术驱动产业未来!
    干货|上云了,如何保障云数据库的高可用?
    直击JDD | 共建智能新城 京东云让城市生活变得简单美好
    2019京东全球科技探索者大会议程抢先曝光!
    京东云入选2019年度TOP100全球软件案例 新一代服务治理框架加速行业落地
    剁手季我做过最牛的事情
    干货|混沌工程落地的六个阶段
    Jenkins 插件中心国内镜像源发布
    list
    queue
  • 原文地址:https://www.cnblogs.com/myseries/p/13453146.html
Copyright © 2011-2022 走看看