我有三个番石榴Service
由番石榴ServiceManager
异步启动。
第一个服务是数据库连接池,需要在第二个/第三个服务成功处理传入消息之前完全启动。显然,这些是异步启动的,数据库可能在第二个/第三个服务开始处理消息之前没有完全启动,这将导致异常。
这里所需的模式是什么?
我可以将数据库服务注入其他服务并在服务启动时调用awaitRunning()
方法,但是当ServiceManager
关闭时我会遇到同样的问题。
答案 0 :(得分:0)
我认为guice没有开箱即用的机制。如春天有一个依赖属性,可以定义一些排序。有一些框架可以为你提供guice(例如dropwizard guicey实现了一个订单注释)。然而,这很容易解决。
方法是使用多绑定为所有依赖类定义管理器。我将这称为Managed(从码头采用)。界面将实现排序。然后,我们使用一个管理器,以一个定义良好的顺序逐个启动所有服务(如果需要,也可以用于关闭)。
请参阅我的代码示例:
public class ExecutionOrder {
public static void main(String[] args) {
Injector createInjector = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
Multibinder<Managed> multiBinder = Multibinder.newSetBinder(binder(), Managed.class);
multiBinder.addBinding().to(Service1.class);
multiBinder.addBinding().to(Service2.class);
bind(ManagedManager.class).in(Singleton.class);
}
});
createInjector.getInstance(ManagedManager.class); // start it
}
public interface Managed extends Comparable<Managed> {
public default void start() {}
public default int getOrder() { return 0;}
@Override
default int compareTo(Managed o) {
return Integer.compare(getOrder(), o.getOrder());
}
}
public static class ManagedManager {
@Inject
public ManagedManager(final Set<Managed> managed) {
managed.stream().sorted().forEach(Managed::start);
}
}
public static class Service1 implements Managed {
@Override
public void start() {
System.out.println("Started Service 1");
}
@Override
public int getOrder() {
return 1;
}
}
public static class Service2 implements Managed {
@Override
public void start() {
System.out.println("Started Service 2");
}
@Override
public int getOrder() {
return 2;
}
}
}
我 - 无可否认地命名 - ManagedManager使用guice的多重绑定通过guice注入所有Managed接口(参见我初始化的模块)。然后我对它进行排序并调用start。
start方法是初始化服务的地方(例如数据库连接)。通过覆盖getOrder()方法,您可以定义在哪个位置启动哪个服务。
通过这种方式,您可以获得定义良好的启动行为,并且您可以调整接口以获得明确定义的关闭行为。
我希望这有帮助,
Artur