2 java dependency-injection guice
我正在使用Guava创建EventBus一个发布 - 订阅消息服务.我也是第一次尝试使用Guice.我已经阅读了Guice教程,并且一直在玩这些AbstractModule和Binder类.但是,当我离开教程并尝试实际为我的项目工作时,我很窒息.
我的项目EventMonitor有一个Guice注入的Guava实例EventBus:
public class EventMonitor {
@Inject
private EventBus guavaEventBus;
// ...
}
Run Code Online (Sandbox Code Playgroud)
在我的应用程序的Guice/DI/Bootstrapping代码中,我定义了一个AbstractModule结论:
public class MyAppModule extends AbstractModule {
@Override
public void configure() {
// Here is where I want to wire together the EventBus to give
// to the EventMonitor.
}
}
Run Code Online (Sandbox Code Playgroud)
最终,我想EventBus通常会构建一个(在非Guice代码中),如下所示:
ThreadFactory factory = ThreadManager.currentRequestThreadFactory();
Executor executor = Executors.newCachedThreadPool(factory)
EventBus eventBus = new AsyncEventBus(executor);
Run Code Online (Sandbox Code Playgroud)
我因为两个(看似不可注入的)静态方法ThreadManager而窒息Executors而且因为我的引用是针对a EventBus而实际的对象是一个AsynEventBus; 因此我不确定如何绑定它:
// Doesn't work because how does Guice know I'm referencing an AsyncEventBus?!?
bind(EventBus.class).toInstance(executor);
// Doesn't work because now I've lost the ability to pass the
// AsyncEventBus an 'executor' and no-arg ctor is used!
bind(EventBus.class).to(AsyncEventBus.class);
Run Code Online (Sandbox Code Playgroud)
所以我问:考虑到我想要构建我的方式EventBus,一个穿着战斗的Guice老手怎么会把这里的东西连接起来(使用ThreadFactory,Executor和EventBus)这样,EventMonitor完全配置EventBus好的注入?我想,一旦我看到这个更"复杂"的例子,我就会开始通过树木看到森林.提前致谢.
一个穿着战斗的Guice老将如何在这里连线
两个词:提供者方法.
public class MyAppModule extends AbstractModule {
@Override
public void configure() {
bind(EventBus.class).to(AsyncEventBus.class);
}
@Provides @Singleton
ThreadFactory providesThreadFactory() {
return ThreadManager.currentRequestThreadFactory();
}
@Provides @Singleton
Executor providesExecutor(ThreadFactory factory) {
return Executors.newCachedThreadPool(factory)
}
@Provides @Singleton
AsyncEventBus providesAsyncEventBus(Executor executor) {
return new AsyncEventBus(executor);
}
}
Run Code Online (Sandbox Code Playgroud)
命名@Provides以"提供"开头的方法的惯例不是guice需要的,但是你真正想做的事情,特别是在大型代码库上.能够在代码体中搜索"提供"并找到提供特定对象的方法.
在评论中回答问题的几点说明:
Guice检查Module您为@Provides方法安装的每个实例,并安装它们,就好像您将方法的返回类型绑定.toProvider到匿名Provider实例一样.所以关于它们的好处是你不需要在configure方法中使用任何额外的代码来使它们使用它们.
该@Singleton注解告诉吉斯,你只想要那个东西一个实例,因此它只会调用该provides*方法一次.默认情况下,如果您将其关闭,则每次需要注入实例时,都要让guice调用您的提供程序和/或实例化一个新对象(取决于您为该类配置的内容).注意:有些人在第一次发现这个时就吓坏了,然后想把它放在@Singleton"效率"的地方 - 这是一种不正确的反应.实际上,您确实希望@Singleton谨慎使用,并且只有在具有多个不同实例的情况下才会使用.
在这种情况下,我们希望确定EventBus周围只有一个.只要您没有直接注入Executor或ThreadFactory进入任何其他类,您可以将注释保留在这些方法之外.对于ThreadFactory这几乎肯定不会有所作为,因为我认为ThreadManager.currentRequestThreadFactory()无论如何它每次都会返回相同的实例.它会有所不同Executor,但也许您想要Executor在其他地方使用它的新实例?
@Provides方法的参数连接方式与配置的其余部分相同.例如,在这种情况下,我知道providesAsyncEventBus会得到Executor返回的providesExecutor那个,因为这是实例guice将在它被要求时注入Executor.如果我有两个这样的方法:
@Provides @Singleton
Executor providesExecutor1(ThreadFactory factory) {
return Executors.newCachedThreadPool(factory)
}
@Provides @Singleton
Executor providesExecutor2(ThreadFactory factory) {
return Executors.newScheduledThreadPool(10, factory)
}
Run Code Online (Sandbox Code Playgroud)
当你尝试创建注入器时,guice会抛出一个配置错误,因为你已经告诉过使用两种不同的方法来获取一个注入器Executor.现在,如果我有这样的事情:
@Provides @Singleton
ExecutorService providesExecutor1(ThreadFactory factory) {
return Executors.newCachedThreadPool(factory)
}
@Provides @Singleton
ScheduledExecutorService providesExecutor2(ThreadFactory factory) {
return Executors.newScheduledThreadPool(10, factory)
}
Run Code Online (Sandbox Code Playgroud)
但仍然有providesAsyncEventBus方法如上,那么当你尝试创建喷油器,因为你没有告诉它如何创建吉斯将抛出一个错误Executor即providesAsyncEventBus要求.你需要一个额外的行,如:
bind(Executor.class).to(ExecutorService.class);
Run Code Online (Sandbox Code Playgroud)
在您的configure方法中解决问题.
至于你的register方法,你有几个选择.到目前为止,我认为最简单的方法是将EventBus参数添加到@Inject需要注册的对象的注释构造函数中,然后evtBus.register(this)作为构造函数的最后一行.
其他选项包括使用静态注入(您可以阅读,但我不建议),或使用多绑定器Set<Object>使用相应的注释绑定a ,然后在创建的相同启动代码中Injector,迭代该集合以注册任何内容.(第二种方法可以在一些不错的模式中完成,但在你了解更简单的guice使用模式之前我不会推荐它)
| 归档时间: |
|
| 查看次数: |
1573 次 |
| 最近记录: |