Guice服务依赖项

时间:2016-09-07 16:48:52

标签: java guice

我有三个番石榴Service由番石榴ServiceManager异步启动。

第一个服务是数据库连接池,需要在第二个/第三个服务成功处理传入消息之前完全启动。显然,这些是异步启动的,数据库可能在第二个/第三个服务开始处理消息之前没有完全启动,这将导致异常。

这里所需的模式是什么?

我可以将数据库服务注入其他服务并在服务启动时调用awaitRunning()方法,但是当ServiceManager关闭时我会遇到同样的问题。

1 个答案:

答案 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