如何延迟spring bean启动?

Posted

技术标签:

【中文标题】如何延迟spring bean启动?【英文标题】:How to delay spring beans startup? 【发布时间】:2011-03-28 11:36:02 【问题描述】:

拥有运行 apache-activemq 服务器作为 spring bean 和几个 apache-camel 路由的 spring 应用程序(实际上是 grails 应用程序)。应用程序使用休眠来处理数据库。问题很简单。 Activemq+Camel 启动BEFORE grails 将特殊方法注入休眠域对象(实际上是保存/更新方法等)。因此,如果 activemq 在启动时已经有一些数据 - Camel 开始处理消息而没有注入 Grails DAO 方法。 grails.lang.MissingMethodException 失败。在 Grails 将特殊方法注入域对象之前,必须延迟 activemq/camel 启动。

【问题讨论】:

【参考方案1】:

如果所有这些都定义为spring bean,则可以使用

<bean id="activeMqBean" depends-on="anotherBean" />

这将确保anotherBeanactiveMqBean 之前初始化

【讨论】:

谢谢 Bonzo,但我知道 depends-on 声明。不幸的是,它不起作用,因为 Grails 初始化与 Spring 在不同的层上。所以没有什么是 activemq 应该依赖的 bean。【参考方案2】:

您可以将 MQ 管理移动到插件中吗?它会增加模块化,如果你在插件描述符中声明

def loadAfter = ['hibernate']

你应该有想要的行为。适用于JBPM plugin

【讨论】:

好吧,老实说,我不会创建/维护单独的插件只是为了在加载休眠后启动 AMQ。我确信有更好的方法。 在 grails 中,插件是组件。我为应用程序开发了几个插件只是因为我认为它们会更好地模块化。插件也是集成遗留数据或系统的有用方法。在维护应用程序时维护它们。您不必将它们释放到野外。 我知道了 ;) 但无论如何 - 我不会将单个 activemq.xml 初始化文件从主应用程序移动到另一个具有完整 grails 插件项目结构的 component 中,将其发布到 svn 和维护另一堆源只是为了延迟 AMQ 初始化。有更简单的方法。 AMQ bean 支持 start 属性,指示它是否应该自动启动。暂时使用它。【参考方案3】:

我不确定你的情况,但延迟加载也可能会有所帮助,例如

<bean id="lazybean" class="com.xxx.YourBean" lazy-init="true">

一个延迟初始化的 bean 指示 IoC 容器在第一次请求它时创建 bean 实例。这可以帮助您延迟加载所需的 bean。

【讨论】:

这也行不通,因为我的 DAO bean 肯定是在加载休眠之前请求的。【参考方案4】:

我知道这个问题已经很老了,但我现在在 2015 年面临同样的问题 - 这个帖子没有为我提供解决方案。

我想出了一个具有 CountDownLatch 的自定义处理器 bean,我在引导应用程序后对其进行倒计时。因此,在应用程序完全启动并为我工作之前,这些消息将处于空闲状态。

/**
 * bootstrap latch processor
 */
 @Log4j
 class BootstrapLatchProcessor implements Processor 
     private final CountDownLatch latch = new CountDownLatch(1)

     @Override
     void process(Exchange exchange) throws Exception 

         if(latch.count > 0)
            log.info "waiting for bootstrapped @ $exchange.fromEndpoint"
            latch.await()
         

         exchange.out = exchange.in
     

     /**
      * mark the application as bootstrapped
      */
     public void setBootstrapped()
         latch.countDown()
     
 

然后将其用作应用程序中的 bean,并在 Bootstrap.groovy 中调用 setBootstrapped 方法

然后,在您的 RouteBuilder 中,您将处理器放置在您的端点和目的地之间,以便在应用启动之前为您期望消息传入的所有路由:

from("activemq:a.in ").processRef('bootstrapProcessor').to("bean:handlerService?method=handle")

【讨论】:

以上是关于如何延迟spring bean启动?的主要内容,如果未能解决你的问题,请参考以下文章

分析 Spring 应用程序以最小化启动时间

Spring IOC源码剖析:lazy-init 延迟加载机制和循环依赖问题

Spring IoC容器实现

让 Spring Boot 应用启动更快

Spring启动流程

Spring-更多DI的知识