我想知道如何将单例绑定到提供程序中的参数。
即:
@Singleton
public class RunButtonController{
@Inject
public RunButtonController(EventBus eventbus){ ... }
public JComponent getView(){
return view;
}
...
}
public class UncaughtExceptionController{
@Inject
public UncaughtExceptionController(
EventBus eventBus, ...,
@Named(DefaultExceptionViewKey) JComponent defaultView)
{ ... }
...
}
public class GUIController{
//another consumer of RunButtonController, arguably the "main" consumer.
@inject
public GUIController(RunButtonController runButtonController,
UncaughtExceptionController uncaughtExceptionController, ...)
{ ... }
...
}
public class Bootstrapper{
public static void main(String[] args){
Injector injector = Guice.createInjector(new OptipModule());
GUIController controller = injector.getInstance(GUIController.class);
}
private static class OptipModule extends AbstractModule{
@Override
protected void configure() {
bind(EventBus.class).toInstance(new EventBus("OPTIPGlobalEventBus"));
bind(JFrame.class).to(GUIView.class);
}
@Provides @Named(DefaultExceptionViewKey)
public JComponent getFrom(RunButtonController runButtonController){
return runButtonController.getView();
}
}
}
在我的RunButtonController
构造函数上设置断点,我可以看到它一直被实例化两次。我希望它只实例一次,我想要
defaultExceptionViewProvider == runButtonController
是true
。
我已经相当广泛地使用了Castle Windsor,但那是我用过的唯一一个IOC容器,所以我是新来的guice。我在整个地方都看到了访问者行为的残余,而guice的文档清楚地表明,类的定义行为(即实例一次,使用此实例,使用此工厂,......)不会持续存在它配置的模块。我想说我写的是当你使用@Provides
时,guice会为你创建一个子模块,所以我需要做的就是告诉这个孩子@提供生成的模块'嘿,这个类是单身,我正在解决它,所以在这里!不要使用你自己的!'
我认为我以错误的方式处理这个框架。我一直在粉碎注释和调试,但也许我真正需要做的是花几个小时阅读一个很好的教程,不幸的是我找不到一个。 JavaDoc有示例,网页发布它们,但是它们给你很少的上下文,所以,在阅读了@Assisted 三次的文章之后,我仍然不理解它(perhalps那是我的意思)应该使用?)奖励积分指向一个特别详细的博主和他的页面上的guice条目的方向。
沿着这些方向,并且极度离题,我想知道我试图推动这个“嘿你的默认通知区域是其他人看到'进入我的IOC容器的后果是什么。这可能是域逻辑吗?我真的不希望UnhandledExceptionController
知道它的视图是由RunButtonController
提供的,同样我也不希望RunButtonController
知道它的视图被用于其他任何其他内容而不是被压印到视图树上。
感谢阅读!
答案 0 :(得分:2)
发布时,看起来您的代码应该可以正常工作。也就是说,有一些警告可能导致单身人士共存。仔细检查每个构造函数调用的堆栈跟踪。
这可能是显而易见的,但您可以在Guice的控制之外创建任意数量的实例,而Guice无法知道这些实例存在。仔细检查代码中的任何内容都不会手动调用RunButtonController
构造函数。
在任何给定的注入器中强制执行Singleton行为。如果您的应用程序中有两个或更多注入器,则每个注入器都可以创建自己的RunButtonController
实例。但是,在父注射器中声明的单例将对任何子注射器可见。
单身人士通过密钥工作。如果您要删除@Singleton
注释并添加此项:
bind(RunButtonController.class)
.annotatedWith(Names.named("Foo"))
.asEagerSingleton()
然后注入RunButtonController
每次都会获得一个新实例,但是注入@Named("Foo") RunButtonController
会得到一个单独的单例实例,每次都会返回相同的实例。这可能不适用于你,因为@Singleton
在班级本身,但它之前已经咬过其他人。
您似乎不依赖继承,但请记住singleton annotations don't inherit from superclass to subclass。
旁注:@Provides
方法不能通过子注入器工作,但私有模块可以(提到“父注射器”in the documentation)。在内部,separate internal module负责调用这些提供者方法,但这并不重要 - 单个模块之间共享。
关于分享视图的离题:通过注入@Named(DefaultExceptionViewKey) JComponent
代替RunButtonController
,您已经做得相当不错,但如果您想要更加与实现无关,那么您可以创建一个{{ 1}}接口和代码。