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

 

抛错:

 

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.stoplifeCycle.stop
ContextStoppedEvent
context.closeContextClosedEvent
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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值