我需要将现有的spring应用程序与自定义的elasticsearch河流集成,ES Rivers使用Google Guice管理它们的依赖关系,并在自己的一组线程中运行。
我创建了一个简单的类,它返回对spring上下文的静态引用,并配置了一个Guice模块,该模块从spring上下文返回对象。为了确保在guice线程和spring线程之间正确同步,我在上下文完全初始化后使用了CountDownLatch
。这是一些代码
public class GuiceSpringIntegrator implements ApplicationListener<ContextRefreshedEvent> {
private static ApplicationContext context;
private static final CountDownLatch contextLatch = new CountDownLatch(1);
@Override public void onApplicationEvent(ContextRefreshedEvent event) {
try {
// check some stuff in context
} finally {
log.debug("Setting application context as static field of {}", getClass().getSimpleName());
GuiceSpringIntegrator.context = event.getApplicationContext();
log.info("Releasing latch for application context");
contextLatch.countDown();
}
}
public static ApplicationContext getApplicationContext() {
if (null == context) {
log.info("ApplicationContext not yet initialized, wait for it in thread {}", Thread.currentThread().getName());
Uninterruptibles.awaitUninterruptibly(contextLatch); <-- !!! SPRING INITIALIZATION CODE HANGS HERE
log.debug("Returning application context since now context is initialized");
Preconditions.checkState(context != null, "ApplicationContext should have been initialized properly");
}
return context;
}
}
这是使用上面的类
的guice模块/**
* Guice module configuration
*/
public class ElasticSearchModule extends AbstractModule {
@Override
protected void configure() {}
@Provides @Singleton TaskScheduler getSchedulerInstance() {
return GuiceSpringIntegrator.getApplicationContext().getBean(TaskScheduler.class);
}
// and so on...
}
但是,当我启动应用程序时(特别是在快速服务器上),应用程序偶尔挂起在上面代码中标记的行。我仔细检查了导致#getApplicationContext()
方法调用的每个代码路径,并且它们(应该)由guice调用,因此最终应该释放锁存器并且代码应该继续。
#getApplicationContext
?#onApplicationEvent
?答案 0 :(得分:0)
除了第4点之外,这并没有真正回答你的问题,但我想编写代码,以便我将其作为答案而不是评论。
我会尝试改变这个:
Uninterruptibles.awaitUninterruptibly(contextLatch); <-- !!! SPRING INITIALIZATION CODE HANGS HERE
到此:
boolean awaitResult = Uninterruptibles.awaitUninterruptibly(contextLatch, 2, TimeUnit.MINUTES);
if(awaitResult) {
throw new IllegalStateException("Unable to load Spring Context");
}
然后你可以在某处捕获该异常并将其堆栈跟踪写入日志;这不会解决您的问题,但它可能会让您更加了解死锁的位置?