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;
}
}