Pregunta

Soy bastante nuevo en Guice, así que espero que esta no sea una pregunta obvia ...

Estoy tratando con un marco que instancia dinámicamente una de mis clases de aplicación (llamémoslo C) Usando la reflexión, por lo que no tengo control sobre su instanciación. Además, no hay una manera fácil de acceder a un recién creado C Después de que el marco lo haya instantado. Esto es lo que C se vería como:

    public class C implements I {

        public C() {
            // this ctor is invoked by the framework so can't use DI here?
        }        

        public void initialize() {
            // this is a post instantiation hook which the f/w will invoke
        }

        private void m() {
            Dependency d = Dependency.getInstance();
            d.doSmth();
        }
    }

Me gustaría C adquirir Dependency Usando Di. Aquí Dependency Es claramente un singleton, pero este no es necesario que sea el caso en general.

Me he encontrado dos posibles soluciones, ninguna de las cuales se siente muy ordenada, así que pensé en preguntarle a los expertos:

  1. Inyección estática. Sin embargo, me cuesta ver cómo esto mejora drásticamente sobre el localizador del localización de servicio: termino con campos estáticos no finales que podrían manipularse externamente ... hmmm.

  2. El marco admite un gancho para C para inicializarse después de la instanciación (el initialize() Método que se muestra arriba). Este método podría autoinyectar la instancia recién creada usando la inyección de setter.

Con 2, supongo que esto significa más alterabilidad externa, pero al menos expone la dependencia un poco más explícitamente para cosas como las pruebas unitarias. El problema es: ¿cómo tengo mis manos en el inyector Guice en ese caso (sin confiar en otro localizador de servicios)? También he leído (y tiende a estar de acuerdo) con que referirse explícitamente al inyector a lo largo del código de la aplicación es una práctica dudosa.

Tu visión sería realmente apreciada.

Muchas gracias,
cristiano

¿Fue útil?

Solución

Puede intentar inyectar a los proveedores estáticamente en la inyección estática de C. más incómoda para probar. Pero los proveedores hacen posible que Guice valida sus dependencias con entusiasmo, mientras las crea perezosamente.

public class C implements I {
  @Inject static Provider<Dep1> dep1Provider;
  @Inject static Provider<Dep2> dep2Provider;

  ...

  public void initialize() {
    Dep1 dep1 = dep1Provider.get();
    Dep2 dep2 = dep2Provider.get();
    ...
  }
}

Otros consejos

Si hace que su inyector Guice esté disponible mediante la variable estática y los métodos de accesor de estática, puede resolverlo así:

public class C implements I {

    public C() {
        // this ctor is invoked by the framework, you can't do injection here.
    }        

    public void initialize() {
        MyGuice.getInjector().inject(this);
    }

    @Inject
    protected void init(Dep1 dep1, Dep2 dep2) {
        this.dep1 = dep1;
        this.dep2 = dep2;
    }

    private void m() {
        dept1.doSmth();
    }
}

La llamada estática es un poco antipatrón, puede eliminar esa dependencia con una anotación simple que se encarga de la inyección posterior al constructor si está dispuesto a usar una solución que hace un tejido de código o un paso de compilación posterior. De esta manera, puede inyectar todos los objetos incluso si no tienen un método de inicialización. Puede encontrar un ejemplo de esto aquí: Cómo inyectar objeto modelo con aspectoJ.

@Configurable
public class C implements I {

    public C() {
        // this ctor is invoked by the framework, you can't do injection here.
    }        

    @Inject
    protected void init(Dep1 dep1, Dep2 dep2) {
        this.dep1 = dep1;
        this.dep2 = dep2;
    }

    private void m() {
        dept1.doSmth();
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top