2

很多时候,类需要被实例化(构造),然后“连接”(配置)才能使用。例如:

// Construction.
EventBus bus = new EventBus();
FizzEventHandler fizzHandler = new FizzHandler();
BuzzEventHandler buzzHandler = new BuzzHandler();

// Wiring.
bus.register(fizzHandler);
bus.register(buzzHandler);

在 Guice 中,我们通过以下方式完成第一部分(构造;注入)Binder

public class MyModule extends AbstractModule {
    @Override
    public void configure() {
        bind(EventBus.class).to(SimpleEventBus.class);
        bind(FizzEventHandler.class).to(DefaultFizzEventHandler.class);
        bind(BuzzEventHandler.class).to(DefaultBuzzEventHandler.class);
    }
}

但是布线发生在哪里?当我的基于 Guice 的应用程序启动时,我们使用 DI“引导”过程:

public class MyApp {
    private EventBus bus;
    private FizzEventHandler fizzHandler;
    // ...etc.

    public static void main(String[] args) {
        MyApp app = new MyApp();
        app.run();
    }

    public MyApp() {
        // Bootstrap DI.
        MyModule myModule = new MyModule();
        Injector injector = Guice.createInjector(myModule);

        bus = injector.inject(EventBus.class);
        fizzHandler = injector.inject(FizzEventHandler.class);
        // ...etc.

        // Wire
        bus.register(fizzHandler);
    }
}

这适用于顶级(根)DI 类。但是随着我们进一步“向下”依赖树,并进入应用程序使用的所有其他对象,将连接逻辑放在这样的构造函数中是丑陋的并且(我相信)是一种不鼓励的做法。

所以我问:厌战的 Guice 退伍军人将他们的接线/配置代码放在哪里?

4

3 回答 3

3

我在一个使用 Guice 的相当大的系统(约 3000 个类)上工作。我想说我们的方法是用构造函数做所有事情。正如您所描述的,没有明显的“建设”和“布线”活动,只有建设。

在您的示例中,事件处理程序将是总线的构造函数参数,它将在其构造函数中注册它们。

如果您想相当灵活地注入给定类型的所有组件(在这里,您希望将所有事件侦听器注入总线),您可以使用multibindings。但是,我认为我们实际上并没有在我们的代码库中使用它。我们只是写出需要注入的所有东西的手动列表,事实证明这在实践中并不是那么困难。

于 2013-02-02T15:50:40.970 回答
2

我一般使用多个模块,按逻辑功能分开。所以一个模块可能有身份验证,另一个有数据存储库,另一个是我正在使用的消息传递系统,等等。这允许你有不同的模块来模拟、缓存 Vs. 非缓存,或者只是同一服务的不同实现,并快速轻松地切换依赖块。

为了让事情变得更加灵活,你可以有一个配置文件来声明注入器启动时应该使用的模块。

于 2013-02-02T13:46:50.833 回答
0

当我在实例化我的对象后立即完成一些逻辑时,我通常在使用@Provides 注释的方法中执行它。您的示例可能如下所示:

public class MyModule extends AbstractModule {
   @Override
   protected void configure() {

    bind(FizzEventHandler.class).to(DefaultFizzEventHandler.class);
    bind(BuzzEventHandler.class).to(DefaultBuzzEventHandler.class);

   }


   @Provides
   public EventBus getEventBus(SimpleEventBuss simpleBus/* this here is going to be injected as it is a class not an interface and Guice is clever and it know how to do it ;) */
     , FizzEventHandler fizz, BuzzEventHandler buzz) {
    simpleBus.register(fizz);
    simpleBus.register(buzz);
    return simpleBus;
   }
  }
于 2014-06-20T00:35:46.943 回答