我想知道如何将单例绑定到提供程序中的参数。
即:
@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
为CCD_ 3。
我使用过温莎城堡相当广泛,但那是我唯一使用过的国际奥委会集装箱,所以我是新手。我看到到处都是访问者行为的残余,guice的文档非常清楚地表明,类的定义行为(即,实例一次,使用此实例,使用此工厂,…)不会在为其配置的模块之外持续存在。我想说的是,我看到它写道,当你使用@Provides
时,guice会为你创建一个子模块,所以我需要做的大概是告诉这个child@Providers生成的模块,‘嘿,这个类是一个singleton,我正在解决它,所以它就在这里!不要用你自己的
我认为我对这个框架的理解是错误的。我一直在破坏注释并进行调试,但也许我真正需要做的是花几个小时阅读一个好的教程,不幸的是我找不到。JavaDoc有一些例子,网页会发布它们,但它们给你的上下文很少,所以,在@Assisted上读了三遍的文章后,我仍然不明白(也许这就是我应该使用的?)对于那些指向一个特别详细的博主和页面上的指导条目的人来说,这是一个加分项。
沿着这些思路,我非常离题,我想知道我试图把这个"嘿,你的默认通知区域是其他人的视图"推到我的国际奥委会容器里会有什么后果。这可能是域逻辑吗?我真的不想让UnhandledExceptionController
知道它的视图是由RunButtonController
提供的,同样,我也不希望RunButtonController
知道它的观点被用于除被冲压到视图树之外的任何事情。
感谢阅读!
正如所发布的,您的代码看起来应该可以工作也就是说,有一些注意事项可能会导致单身汉共存。仔细检查每个构造函数调用的堆栈跟踪。
-
这可能是显而易见的,但您可以在Guice的控制之外创建任何数量的实例,而Guice无法知道这些实例的存在。仔细检查代码中是否没有任何内容手动调用
RunButtonController
构造函数。 -
Singleton行为是在任何给定的注入器中强制执行的。如果您的应用程序中有两个或多个注入器,它们可以各自创建自己的
RunButtonController
实例。但是,在父注入器中声明的singleton对任何子注入器都是可见的。 -
辛格尔顿通过键工作。如果要删除
@Singleton
注释并添加以下内容:bind(RunButtonController.class) .annotatedWith(Names.named("Foo")) .asEagerSingleton()
然后注入
RunButtonController
每次都会得到一个新实例,但注入@Named("Foo") RunButtonController
每次都会获得一个单独的单例实例,该实例每次都会返回相同的实例。这可能不适用于您,因为@Singleton
本身就在类上,但它以前也咬过其他类。 -
您似乎不依赖于继承,但请记住,singleton注释不会从超类继承到子类。
附带说明:@Provides
方法不通过子注入器工作,但私有模块可以(在文档中被间接称为"父注入器")。在内部,确实有一个单独的内部模块负责调用这些提供程序方法,但这并不重要——singleton在模块之间共享。
关于您关于共享视图的题外话:通过注入@Named(DefaultExceptionViewKey) JComponent
而不是RunButtonController
,您已经做得相当好了,但如果您想更不了解实现,您可以创建一个ExceptionHandlerComponent
接口并编写相应的代码。