Java Guice:注入vs布线

Java Guice:注入vs布线,java,dependency-injection,guice,Java,Dependency Injection,Guice,很多时候,类需要实例化(构造),然后“连接”(配置)才能使用。例如: // Construction. EventBus bus = new EventBus(); FizzEventHandler fizzHandler = new FizzHandler(); BuzzEventHandler buzzHandler = new BuzzHandler(); // Wiring. bus.register(fizzHandler); bus.register(buzzHandler);

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

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

// Wiring.
bus.register(fizzHandler);
bus.register(buzzHandler);
在Guice中,我们使用
活页夹完成第一部分(构造;注入):

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“引导”过程:

这对于顶级(根)DI类来说是可行的。但是,当我们进一步“向下”依赖关系树,并进入应用程序使用的所有其他对象时,像这样将布线逻辑放在构造函数中是很难看的,而且(我相信)是一种令人沮丧的做法


所以我问:厌倦战斗的美国能源部Guice老兵把他们的接线/配置代码放在哪里?

我通常使用多个模块,由逻辑功能分开。因此,一个模块可能包含身份验证,另一个模块包含数据存储库,另一个模块包含我正在使用的消息传递系统,等等。这允许您使用不同的模块进行模拟、缓存与非缓存,或者只是同一服务的不同实现,并快速轻松地切换依赖项块


为了使事情更加灵活,您可以有一个配置文件,其中声明了喷油器启动时应使用的模块。

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

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


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

当我在实例化对象之后有一些逻辑要做时,我通常用@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;
   }
  }

有趣-谢谢@jgm(+1)。至于最后一部分(声明模块的配置文件),它是内置于Guice还是自主开发的?此外,我喜欢您将DI分散到不同模块中的想法,但这仍然不能告诉我您在哪里进行实际的“布线”。您是在模块的
configure()
方法中还是在其他地方这样做的?再次感谢!配置文件是自产的。就布线而言,在下游方面,您不应该有很多事情要做,只要您在相关构造函数中使用
@Inject
,因为Guice将自己为您做很多工作。
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;
   }
  }