Spring bean创建流程:如何知道它何时完成?

时间:2016-12-13 09:55:48

标签: java spring spring-bean spring-ioc

我有一个spring应用程序,并且有一个计划逻辑,它以固定速率生成原型bean。

我的笔记本电脑上的一切正常,但在将其部署到服务器后,我的应用程序无法启动,原因是:

2016-12-13 04:13:01.885 ERROR 4688 --- [TaskScheduler-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task.
...
BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'metaDataSourceAdvisor': 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!)
...

这是第一个预定的电话。看起来像是一个时间问题。在我的笔记本电脑上,应用程序初始化的速度要快得多,并且第一次调度调用(生成原型bean)没有任何错误。

有没有办法了解Spring bean创建流程的当前状态,以便我可以在计划逻辑中检查它,并且在应用程序创建未完成时不产生任何内容?

谢谢!

1 个答案:

答案 0 :(得分:1)

查看Spring源代码(4.3.3和4.2.2),这只发生在一个位置DefaultSingletonBeanRegistry.getSingleton()中,并且仅在spring上下文的初始化失败时,或者您已明确关闭它。 Spring使用单个线程(调用线程)来创建bean并调用start生命周期方法,因此只有在违反此原则时才能发现异常。

  • 当你说计划任务时,你是指由Spring安排(使用@Scheduled),还是你有自己的调度逻辑?
  • 你是否在你的应用程序中启动任何线程,如果是,那么拥有该线程的bean是否实现了Spring的生命周期或SmartLifecycle接口?

我见过很多开发人员在bean构造函数中启动线程,这是一个非常糟糕的主意。如果你有一个带有生命周期的bean(线程,资源池),你应该总是使用LifeCycle接口,并在start()中创建你的资源,并在stop()中清理它。这是一个好主意,因为在实例化每个eager单例并完全连接上下文之后调用start(),因此除非可以构造每个bean,否则不会创建任何线程。