抛错:

 

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的关闭流程 ,ClassPathXmlApplicationContext#doClose()方法内:

   

 

    故选用ApplicationListener<ContextClosedEvent>接口,细节见下文附录.
 

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

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

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

 

阶段 执行
context.stop lifeCycle.stop
ContextStoppedEvent
context.close ContextClosedEvent
lifeCycle.stop
destroyBeans()"修改singletonsCurrentlyInDestruction为true"

 



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

 

思考题:  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 {

}

                
public class ClassPathXmlApplicationContext{

 doClose(){              

             publishEvent(new ContextClosedEvent(this)); 如果内部配置对应的线程池,那么久可能异步,实现ApplicationListener类.
              getLifecycleProcessor().onClose(); 实现lifeCycle类. smartLiefeCycle是异步
 }

}



 

   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

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐