2012-03-19 14 views
12

Quiero utilizar google guice para hacer que las propiedades estén disponibles en todas las clases de mi aplicación. Definí un Módulo que carga y vincula el archivo de propiedades Test.properties.Uso de Google Guice para inyectar propiedades de Java

Property1=TEST 
Property2=25 

package com.test;

import java.io.FileNotFoundException; 
import java.io.FileReader; 
import java.io.IOException; 
import java.util.Properties; 

import com.google.inject.AbstractModule; 
import com.google.inject.name.Names; 

public class TestConfiguration extends AbstractModule { 

    @Override 
    protected void configure() { 
    Properties properties = new Properties(); 
    try { 
     properties.load(new FileReader("Test.properties")); 
     Names.bindProperties(binder(), properties); 
    } catch (FileNotFoundException e) { 
     System.out.println("The configuration file Test.properties can not be found"); 
    } catch (IOException e) { 
     System.out.println("I/O Exception during loading configuration"); 
    } 

    } 
} 

Estoy usando una clase principal donde creo un inyector para inyectar las propiedades.

package com.test; 

import com.google.inject.Guice; 
import com.google.inject.Injector; 

public class Test { 

    public static void main(String[] args) { 
    TestConfiguration config = new TestConfiguration(); 
    Injector injector = Guice.createInjector(config); 
    TestImpl test = injector.getInstance(TestImpl.class); 
    } 
} 

package com.test; 

import com.google.inject.Inject; 
import com.google.inject.name.Named; 

public class TestImpl { 
    private final String property1; 
    private final Integer property2; 

     @Inject 
     public TestImpl(@Named("Property1") String property1, @Named("Property2") Integer property2) { 

     System.out.println("Hello World"); 
     this.property1 = property1; 
     this.property2 = property2; 

     System.out.println(property1); 
     System.out.println(property2); 

     } 
    } 

Ahora mi pregunta. Si mi TestImpl crea otras clases donde también necesito inyectar propiedades, y esas clases también necesitan inyectar propiedades, ¿cuál es la forma correcta de hacerlo?

  1. Pase el inyector para todas las subclases y luego usar injector.getInstance (...) para crear las subclases?

  2. instanciar un nuevo inyector como

    TestConfiguration config = new TestConfiguration(); 
    Injector injector = Guice.createInjector(config); 
    TestImpl test = injector.getInstance(TestImpl.class); 
    

en todas las clases anidadas?

  1. ¿Existe algún otro enfoque para que las propiedades estén disponibles en todas las clases?
+2

hay una razón por la que es nuevo 'ellos manualmente en lugar de usar guice para inyectarlos en tu clase de prueba (¿cuál sería la forma normal)? – Matt

+0

¿Quiere decir por qué "TestConfiguration config = new TestConfiguration();"? ¿Puedes dar un ejemplo de cómo hacerlo de otra manera? – markus

+0

@markus: No, no 'TestConfiguration' ... es normal que los' nuevos' módulos. La pregunta es acerca de 'TestImpl' creando otras clases donde también necesita inyectar propiedades. Normalmente, declararías esas otras clases (o 'Provider's de ellas) como dependencias de' TestImpl' para que Guice pueda crearlas en lugar de que las crees con 'new' en' TestImpl'. – ColinD

Respuesta

11

Pase el inyector a todas las subclases y luego use inyector.getInstance (...) para crear las subclases?

no, al hacer esto usted está derrotando el propósito del patrón dependency injection y también acoplando toda su implementación a Guice. Sus implementaciones no deberían interactuar en absoluto con guice, excepto a través de las anotaciones (ahora estandarizadas).

instanciar un nuevo inyector como

TestConfiguration config = new TestConfiguration(); 
Injector injector = Guice.createInjector(config); 
TestImpl test = injector.getInstance(TestImpl.class); 

en todas las clases anidadas?

no, y esto es aún peor porque terminará con inyectores múltiples, por lo tanto, múltiples contextos que impedirán un uso adecuado del scopes.

Idealmente, solo debe usar el inyector durante el arranque de su aplicación. Por supuesto, la forma de arrancarlo dependerá en gran medida de la aplicación.

¿Existe algún otro enfoque para que las propiedades estén disponibles en todas las clases ?

Las propiedades se pueden inyectar de la misma forma que lo hizo con TestImpl. Si quiere que TestImpl use, digamos un servicio que también necesita algunas propiedades (u otros servicios), solo deje que Guice lo inyecte en TestImpl. Guice se está ocupando de todas las instancias/cableado. Sólo debe decirle Guice "cómo proceder", utilizando el aglutinante, cuando Guice no puede resolver esto en sí:

public class TestImpl { 
    private final String property1; 
    private final Integer property2; 
    private final IService service; 


     @Inject 
     public TestImpl(@Named("Property1") String property1, @Named("Property2") Integer property2, IService service) { 
      this.property1 = property1; 
      this.property2 = property2; 
      this.service= service; 
     } 
    } 
} 
0

"Ahora mi pregunta. Si mi TestImpl crea otras clases donde también necesito inyectar propiedades, y esas clases también necesitan inyectar propiedades, ¿cuál es la forma correcta de hacerlo?"

Regla de oro: evite el uso de "nuevo" Salvo que sea absolutamente necesario, no permita que su clase Impl "cree otras clases". En cambio, dígale a su TestImpl que cuando se crea con guice, debe obtener las instancias requeridas.

1

La biblioteca Guice configuration puede inyectar para usted los valores de Propiedades o archivos JSON a sus servicios.

Usted puede inyectar desde el archivo application.properties a su servicio como:

@BindConfig(value = "application", syntax = PROPERTIES) 
public class Service { 

    @InjectConfig 
    private int port; 

    @InjectConfig 
    private String url; 

    @InjectConfig 
    private Optional<Integer> timeout; 
} 

Debe basta con instalar los módulos ConfigurationModule

public class GuiceModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     install(ConfigurationModule.create()); 
     requestInjection(Service.class); 
    } 
} 
Cuestiones relacionadas