2011-11-08 11 views
8

Tengo algunos problemas para entender cómo funcionan las instancias únicas de Guice. He leído la documentación disponible (aquí - http://code.google.com/p/google-guice/wiki/Scopes), pero todavía no puedo entender algunas cosas:Guice impasible/lazy singleton instanceiations

1) He integrado Guice con Tomcat, y he configurado algunos enlaces en un ServletModule:

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

(donde la clase MyOtherServlet tiene una anotación @Singleton encima de ella) Mi intención era tener dos servlets, donde uno se crea una instancia con impaciencia, mientras que el otro no lo es. Sin embargo, parece que la línea "servir ... con ..." crea automáticamente objetos de servlets, a pesar de que esa clase no está vinculada como un singleton ansioso. El enlace que adjunté anteriormente menciona la diferencia entre Guice que se ejecuta en Stage.Development y Stage.Production; sin embargo, esto aún sucedió incluso cuando utilicé Stage.Development (que es el predeterminado de todos modos). ¿Hay alguna forma de evitar esto?

2) (continúa 1) Tratando de asegurar que MyServlet se instancia primero aunque todos los servlets ejemplifiquen ansiosamente ahora, he modificado el orden de los módulos (y declaraciones vinculantes) al crear un inyector, de modo que el enlace para MyServlet aparece primero Sin embargo, encontré que todavía se crea una instancia más tarde que otras encuadernaciones (de clases no servlet), que eran de la forma:

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

a pesar de que esos otros enlaces aparecieron más tarde en los módulos/orden de enlace. Lo he investigado, y he descubierto que Guice simplemente ejemplifica singletons ansiosos que estaban vinculados por la forma de "bind ... to ... asEagerSingleton()" antes de hacer uno de "bind ... asEagerSingleton()" , y así lo resolví modificando la línea: bind (MyServlet.class) .asEagerSingleton(); en: bind (MyServletDummyInterface.class) .para (MyServlet.class) .asEagerSingleton()

y que efectivamente trabajadas. Aún así, prefiero evitar tener una interfaz ficticia solo para resolver esto, así que me preguntaba si alguien tenía una mejor solución para esto ...

3) Tengo dos módulos de Guice: un ServletModule y un AbstractModule. Los configureServlets ServletModule() tiene la siguiente unión en ella:

serve("aUrl").with(SomeServlet.class); 

configure de la AbstractModule() tiene las siguientes fijaciones:

bind(SomeImpl.class).asEagerSingleton(); 
bind(SomeInterface.class).to(SomeImpl.class).in(Singleton.class); 

Además, la clase SomeServlet tiene un campo inyectada de tipo SomeInterface, y tiene una anotación @Singleton en la parte superior de la clase.

Ahora, uno esperaría que al crear un inyector, la clase SomeImpl se instanciará, y la misma instancia se inyectará en la instancia de SomeServlet. Como se mencionó anteriormente, los servlets delimitados con una instrucción "servir ... con ..." también parecen obtener una instancia entusiasta, pero de todos modos solo debería haber un solo objeto SomeImpl instanciado. Sin embargo, por alguna razón, obtuve dos objetos SomeImpl instanciados al hacer esto. Para conseguir alrededor de él, he mezclado las dos líneas en la configuración() un poco, y en lugar de lo anterior que tuve allí las siguientes líneas:

bind(SomeImpl.class).in(Singleton.class) 
bind(SomeInterface.class).to(SomeImpl.class).asEagerSingleton(); 

y luego funcionó bien, y ya ha recibido sólo una instancia de SomeImpl instanciado.Realmente no entiendo por qué el interruptor debería importar: puedo ver cómo la última forma es "mejor", pero espero que ambas funcionen correctamente, así que me pregunto si estoy obteniendo algo mal aquí. ?



Lo siento por la longitud,
Gracias por la ayuda!

Respuesta

7

1) No hay forma de evitar esto, ya que Guice llama al método init() de todos los servlets en la inicialización de su propia canalización de filtro y así los construye a todos. Si realmente necesita una lógica de inicialización tan vaga, debe colocarla en el propio servlet (o usar una clase auxiliar desacoplada, o ... hay muchas maneras, dependiendo de su caso de uso).

2) En general, los módulos de Guice declaran los enlaces, no están diseñados para ser definiciones de arranque con órdenes precisas de creación de instancias. Si necesita una orden de instanciación definida, cree los objetos usted mismo en el orden deseado y conéctelos a través del bind(...).toInstance(...). Si necesita inyección en las instancias autoconstruidas, puede usar requestInjection(...) (si la inyección de campo/método es suficiente, es más engorroso para la inyección del constructor).

3) El alcance de Guice se aplica a la clave de enlace, no al valor de enlace, Applying Scopes describe por qué solo su segundo ejemplo funciona según lo previsto.