2010-09-29 25 views
7

Estoy creando una biblioteca que se incluirá como un contenedor, por lo que no contendrá un método principal. Me pregunto cuál es la mejor práctica para poner a Guice en este caso. Tengo un singleton de nivel superior.Uso de Guice sin un método principal

public class TestManager 
{ 
    private TestManager() 
    { 
    } 

    public static TestManager getInstance() 
    { 
     // construct and return singleton 
    } 

    public void createSomeObjects() 
    { 
    } 

} 

¿Dónde debo ir a bootstrap Guice? Estaba pensando que en el constructor podría llamar a Guice.createInjector (nuevo Módulo()); pero no inyectaría ninguno de los objetos creados en createSomeObjects().

¿Hay una manera común de hacer esto cuando no tienes un método principal()?

Saludos.

Respuesta

8

Al igual que las configuraciones de registro, si se trata de una verdadera biblioteca entonces sus opciones son más o menos esto:

  • avisar al usuario de la biblioteca que son responsables de arranque Guice sí mismos.
  • proporcionar un método de inicialización biblioteca que se encarga de arranque Guice si quieren utilizar su biblioteca

Tratando de hacer el super-inteligente como para hacer auto-configuración de la biblioteca a menudo termina con un tanto inflexible, duro para probar jerarquías de clase.

+5

Ofrecer a sus clientes un módulo Guice podría funcionar muy bien. –

+1

+1 para autoconfiguración súper inteligente. Solo piensa en lo malo que fue con Apache Commons Logging. –

+0

@Jesse, nunca he visto bibliotecas que usen Guice internamente realmente lo expongan a los usuarios finales. Por ejemplo, Maven y JIRA usan IoC detrás de escena, pero lo insertan en sus clases sin que usted sepa qué implementación utilizan. Exponer Guice suena más limpio (si el usuario se siente cómodo con Guice), pero me temo que podría asustar a los usuarios (¿por qué nadie más lo hace?). – Gili

0

Esto no es lo que debe qué, pero lo que podría qué:

Deje clases clave en su biblioteca se extienden o no referencia a una clase que inicializa todo en un bloque estático. Este es un truco muy sucio, pero si se asegura de que no se pueda acceder a su API sin que el cargador de clases cargue su clase de inicializador, debe estar seguro.

Puede hacer que sea un poco más limpio si utilizó AspectJ e inyectó un miembro privado del tipo de inicializador en todas las clases de su biblioteca (sin tocar el código java), pero aún así sería un hack.

0

Si solo está utilizando Guice en el ámbito de su biblioteca y no para toda la aplicación, entonces podría usar un bloque estático en la clase TestManager.

Esta estrategia asume que la aplicación va a llamar al TestManager.getInstance() en algún momento y que es el único punto de entrada en su API.

@Singleton 
class TestManager { 

    private static final TestManager INSTANCE; 

    static { 
    INSTANCE = Guice.createInjector(new Module()).getInstance(TestManager.class); 
    } 

    private TestManager() { 
    } 

    public static TestManager getInstance() { 
     return INSTANCE; 
    } 

    @Inject 
    public void createSomeObjects(YourDependencies ...) { 
    // Do something with dependencies 
    } 
}