我有些困惑如何理解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,其中一个是急切地被实例化,而另一个则不是。然而,似乎“serve...with...”语句会自动实例化servlet对象,即使该类未绑定为急切的singleton。 我附上的链接提到了Guice在Stage.Development和Stage.Production下运行的区别,但即使我明确使用了Stage.Development(默认情况下),这种情况仍然发生。 有没有办法避免这种情况?
(接续1) 为了确保MyServlet首先被实例化,即使现在所有servlet都是急切地实例化,我修改了模块的顺序(以及绑定语句),使得MyServlet的绑定出现在第一位。然而,我发现它仍然比其他绑定(非servlet类的绑定)晚实例化,这些绑定的形式如下:
bind(MyInterface.class).to(MyClass.class).asEagerSingleton()
尽管其他绑定出现在模块/绑定顺序中的后面。 我研究了一下,并发现Guice只是在执行“bind... to... asEagerSingleton()”形式的单例之前,实例化通过此形式绑定的单例,而不是通过“bind... 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实例。我真的不明白为什么开关会有所影响 - 我可以看到后一种方法是“更好”的,但我期望两种方法都能正确地工作,所以我想知道我是否在这里弄错了什么...