Guice渴望/懒惰的单身实例化

我有一些麻烦,了解Guice的单例实例化是如何工作的。 我已阅读了可用的文档(此处为http://code.google.com/p/google-guice/wiki/Scopes ),但我仍然无法弄清楚一些事情:

1)我已经将Guice与Tomcat集成在一起,我在ServletModule中设置了一些绑定:

bind(MyServlet.class).asEagerSingleton(); serve("myUrl").with(MyServlet.class); serve("myOtherUrl").with(MyOtherServlet.class); 

(其中MyOtherServlet类上面有一个@Singleton注释)我的意图是有两个servlet,其中一个是急切实例化的,而另一个则没有。 然而,似乎“serve … with …”行自动实例化servlet对象,即使该类未被绑定为急切的单例。 我上面提到的链接提到了在Stage.Development和Stage.Production下运行的Guice之间的区别 – 但是即使我明确使用了Stage.Development(无论如何都是默认的),这仍然会发生。 有什么方法可以避免这种情况吗?

2)(继续1)尝试确保MyServlet首先被实例化,即使所有servlet现在急切地实例化,我在创建Injector时修改了模块(和绑定语句)的顺序,以便首先显示MyServlet的绑定。 但是,我发现它仍然比其他一些绑定(非servlet类)实例化,其forms如下:

 bind(MyInterface.class).to(MyClass.class).asEagerSingleton() 

即使这些其他绑定在模块/绑定顺序中稍后出现。 我调查了一下,发现Guice只是实例化了那些以“bind … to … asEagerSingleton()”的forms绑定的热切单身人士,然后才进行“bind … asEagerSingleton()”,所以我通过修改行来解决它:bind(MyServlet.class).asEagerSingleton(); into:bind(MyServletDummyInterface.class).to(MyServlet.class).asEagerSingleton()

这实际上有效。 尽管如此,我宁愿避免使用虚拟接口来解决这个问题,所以我想知道是否有人有更好的解决方案..?

3)我有两个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的实例。 我真的不明白为什么开关应该重要 – 我可以看到后一种方式是如何“更好”,但我希望两者都能正常工作,所以我只是想知道我是不是在这里弄错了.. ?

抱歉长度,
谢谢您的帮助!

1)没有办法避免这种情况,因为Guice在自己的filter管道初始化时调用所有servlet的init()方法,从而构造它们。 如果你确实需要这样的惰性初始化逻辑,你应该把它放在servlet本身(或者使用一个解耦的帮助器类,或者……有很多种方法,具体取决于你的用例)。

2)一般来说,Guice的模块声明了绑定 ,没有设计成具有精确实例化顺序的bootstrap定义。 如果您需要这样定义的实例化顺序,请按所需顺序自己创建对象,并通过bind(...).toInstance(...)绑定它们。 如果你需要在自构造实例中注入,你可以使用requestInjection(...) (如果字段/方法注入足够,那么构造函数注入会更麻烦)。

3)Gu​​ice的范围适用于绑定密钥,而不是绑定值, 应用范围描述了为什么只有第二个示例按预期工作。