很多时候,类需要被实例化(构造),然后在它们被使用之前“连线”(配置)。例如:
// 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老兵放置他们的布线/配置代码?
答案 0 :(得分:3)
我在一个使用Guice的相当大的系统(~3000个类)上工作。我会说我们的方法是用构造函数做所有事情。你所描述的并没有明显的“建筑”和“布线”活动,只有建筑。
在您的示例中,事件处理程序将是总线的构造函数参数,它将在构造函数中注册它们。
如果您希望相当灵活地注入给定类型的所有组件(这里,您希望将所有事件侦听器注入总线),则可以使用multibindings。但是,我不认为我们在代码库中实际使用它;我们只写出需要注入的所有东西的手册,这在实践中并不是那么艰难。
答案 1 :(得分:2)
我通常使用多个模块,由逻辑功能分隔。因此,一个模块可能在其中具有身份验证,另一个模块具有数据存储库,另一个模块正在使用,等。这允许您使用不同的模块进行模拟,缓存Vs.非缓存,或只是同一服务的不同实现,并快速轻松地切换出依赖关系块。
为了使事情更加灵活,您可以拥有一个配置文件,该文件声明了注入器启动时应该使用的模块。
答案 2 :(得分: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;
}
}