Usar Google Guice para inyectar propiedades de Java
properties (5)
Quiero usar 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 .
Property1=TEST
Property2=25
paquete 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?
Pase el inyector a todas las subclases y luego use injector.getInstance (...) para crear las subclases?
Instanciate un nuevo inyector como
TestConfiguration config = new TestConfiguration(); Injector injector = Guice.createInjector(config); TestImpl test = injector.getInstance(TestImpl.class);
en todas las clases anidadas?
- ¿Hay algún otro enfoque para hacer que las propiedades estén disponibles en todas las clases?
"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 hacer esto?"
Regla de oro: evite el uso de "nuevo" A menos 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.
La biblioteca "Governator" proporciona una función de mapeo de configuración para la inyección de guice. El enfoque es diferente, pero la carga de los archivos de propiedades está disponible.
https://github.com/Netflix/governator/wiki/Configuration-Mapping
mi enfoque es guice-config guice-config
La configuración de biblioteca de Guice puede inyectarle valores desde propiedades o archivos JSON a sus servicios.
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;
}
Simplemente debe instalar los módulos ConfigurationModule
public class GuiceModule extends AbstractModule {
@Override
protected void configure() {
install(ConfigurationModule.create());
requestInjection(Service.class);
}
}
Pase el inyector a todas las subclases y luego use injector.getInstance (...) para crear las subclases?
no, al hacer esto estás derrotando el propósito del patrón de inyección de dependencia y también conectando toda tu implementación con Guice. Sus implementaciones no deberían interactuar en absoluto con guice, excepto a través de las anotaciones (ahora estandarizadas).
Instanciate 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 evitarán un uso adecuado de los ámbitos .
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.
¿Hay algún otro enfoque para hacer que las propiedades estén disponibles en todas las clases?
Las propiedades se pueden inyectar de la misma manera que lo hizo para TestImpl. Si quiere que TestImpl use, digamos un servicio que también necesita algunas propiedades (u otros servicios), simplemente deje que Guice lo inyecte en TestImpl. Guice se está ocupando de todas las instancias / cableado. Solo debes decirle a Guice "cómo proceder", usando la carpeta, cuando Guice no puede resolver esto por sí mismo:
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;
}
}
}