我在理解 Guice 的单例实例化如何工作时遇到了一些麻烦。我已经阅读了可用的文档(这里 - http://code.google.com/p/google-guice/wiki/Scopes),但我仍然无法弄清楚一些事情:
我已将 Guice 与 Tomcat 集成,并在 ServletModule 中设置了一些绑定:
bind(MyServlet.class).asEagerSingleton(); serve("myUrl").with(MyServlet.class); serve("myOtherUrl").with(MyOtherServlet.class);
(其中 MyOtherServlet 类在其上方有一个 @Singleton 注释)我的意图是有两个 servlet,其中一个被急切地实例化,而另一个则没有。然而,似乎“服务...与...”行会自动实例化 servlet 对象,即使该类未绑定为急切的单例。我在上面附加的链接提到了在 Stage.Development 和 Stage.Production 下运行的 Guice 之间的区别 - 但是,即使我明确使用 Stage.Development (无论如何都是默认的),这种情况仍然发生。有没有办法避免这种情况?
(续 1)试图确保 MyServlet 首先被实例化,即使所有 servlet 现在都急切地实例化,我在创建 Injector 时修改了模块(和绑定语句)的顺序,以便 MyServlet 的绑定首先出现。但是,我发现它的实例化时间仍然比其他一些绑定(非 servlet 类的)晚,这些绑定的形式如下:
bind(MyInterface.class).to(MyClass.class).asEagerSingleton()
即使这些其他绑定稍后出现在模块/绑定顺序中。我研究了一下,发现 Guice 在执行“bind ... asEagerSingleton()”之前,只是简单地实例化了由“bind ... to ... asEagerSingleton()”形式绑定的热切单例,所以我通过修改这一行来解决它:
bind(MyServlet.class).asEagerSingleton();
进入:
bind(MyServletDummyInterface.class).to(MyServlet.class).asEagerSingleton()
这确实有效。不过,我宁愿避免使用虚拟界面来解决这个问题,所以我想知道是否有人对此有更好的解决方案..?
我有两个 Guice 模块 - 一个 ServletModule 和一个 AbstractModule。ServletModule configureServlets() 中包含以下绑定:
serve("aUrl").with(SomeServlet.class); AbstractModule 的 configure() 具有以下绑定:
bind(SomeImpl.class).asEagerSingleton(); bind(SomeInterface.class).to(SomeImpl.class).in(Singleton.class);
此外,SomeServlet 类有一个 SomeInterface 类型的注入字段,并且在类的顶部有一个 @Singleton 注释。
现在,人们会期望在创建注入器时, SomeImpl 类将被实例化,并且相同的实例将被注入到 SomeServlet 实例中。如前所述,以“serve...with...”语句为界的 servlet 似乎也被急切地实例化,但无论哪种方式,仍然应该只实例化一个 SomeImpl 对象。然而由于某种原因,我在执行此操作时实例化了两个 SomeImpl 对象。为了解决这个问题,我在 configure() 中混合了两行,而不是上面的,我有以下几行:
bind(SomeImpl.class).in(Singleton.class)
bind(SomeInterface.class).to(SomeImpl.class).asEagerSingleton();
然后它工作得很好,我只实例化了一个 SomeImpl 实例。我真的不明白为什么开关应该很重要 - 我可以看到后一种方式如何“更好”,但我希望两者都能正常工作,所以我只是想知道我是否在这里遇到问题...... .