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

Spring bean creation flow: how to know when it is finished?

我有一个 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 创建流程的当前状态,以便我可以在计划逻辑中检查它,并且在应用程序创建未完成时不产生任何内容?

谢谢!

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

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

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