从线上问题谈spring生命周期类lifeCycle类和bean的生命周期

来源:互联网 发布:药物合成工艺优化 编辑:程序博客网 时间:2024/05/25 05:36

抛错:

Singleton bean creation not allowed while the singletons of this factory are in destruction " +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)

原因:

     mq未停服,不断的消费mq. 此时. spring正在关闭容器. context.close,destroy. 整个容器正在关闭中.

     事务拦截器获取bean通过applicationContext里获取.判断容器正在关闭,拒绝获取bean.抛错.



解决方案:

   分析: 自然想到通过bean的生命周期来实现(网上文章很多)关闭mq消费线程,DisposableBean 接口或者 "-method" 两个方式.

    看看spring的关闭流程:

   

 

    故选用ApplicationListener接口

  生命生命周期和bean生命周期对比:

总结:  lifeCycle类和bean的生命周期不太一致.

          start如果不调用context.start() 是不会启动的. context构造函数默认调用的是fresh().

          先执行生命周期关闭,执行lifeCycle.stop. 再进行bean的destroy().

阶段执行context.stoplifeCycle.stop
ContextStoppedEventcontext.closeContextClosedEvent
lifeCycle.stop

destroyBeans()"修改singletonsCurrentlyInDestruction为true"

说明:

              publishEvent(new ContextClosedEvent(this)); 有可能异步,实现ApplicationListener类.
                getLifecycleProcessor().onClose(); 实现lifeCycle类. smartLiefeCycle是异步


  


可理解为任务先停,再销毁工作单元.

思考题:  spring的容器关闭回收,回影响 实例的依赖和和内存回收么,会影响什么?

 答:     bean的destroy不会影响已经实例化的object内存回收, 内存引用关系依然在,只不过在spring里的depend关系已经没有了.

附录:

1

Spring的生命周期(转)


2.

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

    /**
     * Handle an application event.
     * @param event the event to respond to
     */
    void onApplicationEvent(E event);

}

public class ContextClosedEvent extends ApplicationContextEvent {

}

                publishEvent(new ContextClosedEvent(this));


   3.

DisposableBeanAdapter.invokeCustomDestroyMethod(Method) line: 300    
DisposableBeanAdapter.destroy() line: 226    
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).destroyBean(String, DisposableBean) line: 498    
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).destroySingleton(String) line: 474    
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).destroySingletons() line: 442    设置            this.singletonsCurrentlyInDestruction = true; 标记容器正在关闭中.

ClassPathXmlApplicationContext(AbstractApplicationContext).destroyBeans() line: 1066    
ClassPathXmlApplicationContext(AbstractApplicationContext).doClose() line: 1040    
ClassPathXmlApplicationContext(AbstractApplicationContext).close() line: 988    


通过eclipse call hiearchary 无法得到这个调用堆栈.


contex
0 0
原创粉丝点击