2011-12-04 15 views
7

Tengo una aplicación web que usa GIN para inyectar dependencias en el punto de entrada.Guice/Gin. Cómo inyectar implementaciones múltiples

private InjectorService injector = GWT.create(InjectorService.class); 

@GinModules({PlaceContollerInject.class, RootViewInject.class}) 
public interface InjectorService extends Ginjector { 

    RootView getRootView(); 
    PlaceController getPlaceConroller(); 

} 

public class RootViewInject extends AbstractGinModule { 

    @Override 
    protected void configure() { 
    bind(RootView.class).to(RootViewImpl.class); 
    } 
} 

necesito una versión móvil que utilizan diferentes RootView aplicación. Las dependencias se describen en el siguiente módulo

public class RootViewMobileInject extends AbstractGinModule { 

    @Override 
    protected void configure() { 
    bind(RootView.class).to(RootViewMobileImpl.class); 
    } 
} 

La pregunta es cómo elegir la dependencia necesaria condicional si necesitamos la versión móvil o por defecto. He visto GWT-GIN Multiple Implementations, pero no he encontrado esa solución porque el proveedor rompe la cadena de dependencias y el patrón de fábrica rompe la capacidad de prueba. En el video "Gran Modular Java con Guice" here (12 minute) se presentó el inyector de Guice con módulos como reemplazo de Factories. Así que mi pregunta es si debo crear diferentes Ginjector para móviles y versiones predeterminadas (como MobileFactory y DefaultFactory) de mi aplicación, o sería una mala práctica y debería configurar una instancia de Ginjector con todas las versiones necesarias. Por ejemplo, con los enlaces de anotación como este.

public class RootViewMobileInject extends AbstractGinModule { 

    @Override 
    protected void configure() { 
    bind(RootView.class).annotatedWith(Mobile.class).to(RootViewMobileImpl.class); 
    } 
} 

y utilizar fijaciones @mobile anotados en GWT punto

@Inject 
    private void setMobileRootView(@Mobile RootView rw) { 
    this.rw = rw; 
    } 

entrada en un ejemplo tan simplificada como anteriormente puede ser que sea posible. Pero si una aplicación tiene más dependencias que necesitan versiones móviles y predeterminadas. Parece que se remonta a fábricas "feísimas" (como se decía en la presentación de Guice) "no probables". Lo siento por mi inglés. Cualquier ayuda es apreciada.

+1

Solo quería agregar que la idea aquí y la solución de @aldanok podrían usarse también para la personalización específica del cliente en la aplicación. Específico del cliente: gwt.xml + módulo de ginebra + implementaciones de interfaz. – MeTTeO

Respuesta

9

Creo que querrá usar el enlace diferido GWT, utilizando el reemplazo de clase para enlazar una versión diferente de su InjectorService dependiendo del agente de usuario. Esto asegurará que la versión móvil solo tenga las implementaciones móviles compiladas (y descargadas)

Así tendría InjectorServiceDesktop, InjectorServiceMobile, que se extenderían desde InjectorService, luego GWT.create (InjectorService.class), y dejarían que el enlace diferido decidiera qué implementación debería usar.

http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsDeferred.html#replacement

Un ejemplo de Ginjector con todas las versiones parece mal, ya que significa todo el código para ambas versiones siempre se descarga (y que sin duda no quieren descargar todos los puntos de vista de escritorio en su aplicación móvil)

EDITAR: Como Thomas señala en los comentarios, dado que los Inyectores son clases generadas, deberá colocar cada InjectorServiceXXX dentro de una clase de soporte simple que GWT.create() 's el InjectorServiceXXX, y use el reemplazo para cambiar entre los titulares.

+5

+1, excepto que no funcionará así: no puede tener reemplazo y generación al mismo tiempo, debe crear un "InjectorServiceHolder" con 2 subclases. Cada uno 'GWT.create()' es una subinterfaz diferente 'InjectorService'. Utiliza el reemplazo en el "soporte" para elegir qué 'InjectorService' usar, y' GWT.create() 'en la subinterfaz' InjectorService' activará la generación de código de GIN. –

+0

¡salud para la corrección! actualizado la respuesta. – aidanok

+0

Gracias por la respuesta. Estoy de acuerdo contigo en que debería usar diferentes Ginjectors. es muy simple y conveniente. Pero ¿qué se supone que debes hacer con el mismo problema del lado de Guice que no tiene la técnica de encuadernación diferida? ¿Qué técnica preferiría anular el módulo base? [Modules.override] (http://stackoverflow.com/questions/7314323/how-to-override-binding-in-gin) o simplemente la herencia de Java. ¿Por qué? Y más ... ¿cómo configurar Ginjector/Injector cuando se necesitan todas las versiones (digamos DefaultView y LoggedInView)? – trupanka

1

Hacer lo que desee es realmente bastante complicado debido a que su interfaz de inyector común, que está anotada con su módulo Gin, no puede apuntar a un módulo abstracto de Gin. El módulo Gin señalado por su interfaz Ginjector debe ser uno concreto. Un módulo de hormigón no puede satisfacer múltiples configuraciones al mismo tiempo.

Así que lo que usted hace es: (a) Cree su interfaz Ginjector, digamos ClientGinjector y su Module, ClientModule, para una aplicación de escritorio.

(b) Cree una segunda interfaz Ginjector, digamos ClientGinjectorTablet, extendiendo la que creó en (a) pero con una anotación GinModule apuntando a un Módulo diferente, digamos ClientModuletablet.

- Ahora tiene dos interfaces Ginjecor por defecto y una secundaria para tabletas, cada una apuntando a un módulo con sus propias implementaciones Configure().

(c) Ahora desea crear Factory para obtener la implementación de su Ginjector Derecho. Puedes hacer esto porque el Ginjector que has creado en (a) y (b) tiene un demonitador común que es la interfaz predeterminada creada en (a). Para crear un facotry abstracto con un método como este: public abstract ClientGinjector getInjector(); Crea dos clases concretas para niños Uno para obtener el Escritorio/Ginjector predeterminado y otro para obtener el Ginjector de tableta.

(d) Ahora configura el gwt.xml de su módulo al igual que Google IO en youtube explica que debería obtener el facotry deseado durante el tiempo de ejecución, utilizando enlaces diferidos GWT para cada fábrica de Ginjector.

(e) En su punto de entrada, lo mejor es no obtener un Ginjector, sino su fábrica para Ginjectors utilizando el enlace diferido GWT. Llama al método abstracto que devuelve un ClientGinjector, su conjunto.

(f) La epopeya falla al final. Guice no le permitirá vincular dos veces la misma clave (clase más anotación), incluso si estuviera usando inyectores diferentes (uno para computadora de escritorio y otro para tableta). Parece que las definiciones de enlace de claves son globales, tan pronto como tenga dos módulos que redefinen las mismas claves, ese es el final de la aventura.

Cuestiones relacionadas