java - property - spring configuration file
¿Cómo configuro Spring para anular parcialmente y opcionalmente las propiedades? (2)
Su configuración es defectuosa al configurar BeanFactoryPostProcessor
con java config los métodos deben ser estáticos. Sin embargo, puede ser aún más fácil, en lugar de registrar su propio PropertySourcesPlaceholderConfigurer
utilice el soporte predeterminado de @PropertySource
.
Replace su configuración de jav a la siguiente
@Configuration
@PropertySource(name="main", value= "${spring.profiles.active}.main.properties")
public class PropertyTestConfiguration {
@Autowired
private Environment env;
@PostConstruct
public void initialize() {
String resource = env.getProperty("spring.profiles.sub") +".main.properties";
Resource props = new ClassPathResource(resource);
if (env instanceof ConfigurableEnvironment && props.exists()) {
MutablePropertySources sources = ((ConfigurableEnvironment) env).getPropertySources();
sources.addBefore("main", new ResourcePropertySource(props));
}
}
@Bean
public Main_PropertyTest main_PropertyTest(@Value("${main.property}") String property) {
Main_PropertyTest main_PropertyTest = new Main_PropertyTest(property);
return main_PropertyTest;
}
}
Esto primero debe cargar dev.main.properties
y adicionalmente test.main.properties
que test.main.properties
las propiedades cargadas anteriormente (cuando están llenas, por supuesto).
Me gustaría tener una configuración de propiedades que, en ciertos entornos, pueda anular propiedades específicas. Por ejemplo, nuestras propiedades JDBC predeterminadas para el desarrollador son:
- db.driverClassName = com.mysql.jdbc.Driver
- db.url = jdbc: mysql: // localhost: 3306 / ourdb
- db.username = root
- db.password =
El problema es que a algunos de nuestros desarrolladores les gustaría tener un nombre de usuario / contraseña diferente en el archivo db, o posiblemente incluso en un archivo alojado no localmente. Lo mismo es cierto para nuestra configuración de rabbitMQ, que actualmente utiliza un localhost similar, instalación guest / guest. Ser capaz de anular las propiedades de ciertos elementos de esta configuración por desarrollador nos permitiría mover gran parte de los requisitos de infraestructura / instalación para construir el software fuera de la máquina local y en servidores dedicados.
He creado un proyecto simple para entender la configuración necesaria para lograr lo que quiero, y esta es mi primera incursión en el mundo de la configuración de propiedades de primavera, ya que hasta ahora, la carga y administración de propiedades se realizaba con algunas características personalizadas. código. He aquí mi arreglo:
class Main_PropertyTest {
public static void main(String[] args) {
String environment = System.getenv("APPLICATION_ENVIRONMENT"); // Environment, for example: "dev"
String subEnvironment = System.getenv("APPLICATION_SUB_ENVIRONMENT"); // Developer name, for example: "joe.bloggs"
System.setProperty("spring.profiles.active", environment);
System.setProperty("spring.profiles.sub", subEnvironment);
try(AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PropertyTestConfiguration.class)) {
Main_PropertyTest main = context.getBean(Main_PropertyTest.class);
main.printProperty();
}
}
private final String property;
public Main_PropertyTest(String property) {
this.property = property;
}
public void printProperty() {
System.out.println("And the property is: ''" + property + "''.");
}
}
Y mi configuración:
@Configuration
public class PropertyTestConfiguration {
@Bean
public static PropertySourcesPlaceholderConfigurer primaryPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setLocation(new ClassPathResource(System.getProperty("spring.profiles.active") + ".main.properties"));
return propertySourcesPlaceholderConfigurer;
}
@Bean
public static PropertySourcesPlaceholderConfigurer secondaryPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setLocation(new ClassPathResource(System.getProperty("spring.profiles.sub") + ".main.properties"));
propertySourcesPlaceholderConfigurer.setIgnoreResourceNotFound(true);
propertySourcesPlaceholderConfigurer.setIgnoreResourceNotFound(true);
propertySourcesPlaceholderConfigurer.setOrder(-1);
return propertySourcesPlaceholderConfigurer;
}
@Bean
public Main_PropertyTest main_PropertyTest(@Value("${main.property}") String property) {
Main_PropertyTest main_PropertyTest = new Main_PropertyTest(property);
return main_PropertyTest;
}
}
Y para completar, mi dev.main.properties y test.main.properties:
main.property=dev
main.property=test
El principal problema es que recibo una excepción de argumento ilegal. Por lo que puedo decir, lo que he escrito debe ser el equivalente javaconfig de este método: http://taidevcouk.wordpress.com/2013/07/04/overriding-a-packaged-spring-application-properties-file- via-an-external-file / Desafortunadamente recibo el siguiente error: java.lang.IllegalArgumentException: No se pudo resolver el marcador de posición ''main.property'' en el valor de cadena "$ {main.property}". Tenga en cuenta que también debo ocuparme del caso donde no hay subentorno, y este es el caso con el que comencé (aunque recibo el mismo error incluso si ambos archivos existen). Si elimino el bean que configura el segundocontenedor de sitios de propiedad de propertys, todo funciona bien (con lo cual quiero decir que dev.main.properties se carga y "Y la propiedad es: ''dev''." Se imprime).
Un problema secundario es que el código no se ve muy bien y cada capa del sistema necesitará dos configuraciones de PSPC para que puedan acceder a estas propiedades. Además, requiere muchas llamadas manuales a System.getProperty (), ya que no pude pasar $ {spring.profiles.active} a PSPC.setLocation ();
Nota: He intentado @PropertySources ({primaryproperties, secondaryProperties}), pero esto falla porque secondaryProperties no existe. También probé el entorno @Autowired Environment; y obtener las propiedades de eso, pero el PSPC secundario hace que el entorno no se autoconecte ...
Entonces, siguiendo esta larga explicación, mis preguntas son:
- ¿Es esta la manera correcta de resolver este problema?
- Si es así, ¿qué hay de malo en mi configuración?
- ¿Cómo puedo simplificar la configuración (si es que lo hago)?
- ¿Hay algún mecanismo alternativo disponible que pueda resolver mi problema?
¡Gracias por tu tiempo! :)
Tuve un problema similar al sobrescribir las propiedades ya existentes en las pruebas de integración
Se me ocurrió esta solución:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {
SomeProdConfig.class,
MyWebTest.TestConfig.class
})
@WebIntegrationTest
public class MyWebTest {
@Configuration
public static class TestConfig {
@Inject
private Environment env;
@PostConstruct
public void overwriteProperties() throws Exception {
final Map<String,Object> systemProperties = ((ConfigurableEnvironment) env)
.getSystemProperties();
systemProperties.put("some.prop", "test.value");
}
}