Como configuro o Spring para substituir parcialmente e opcionalmente as propriedades?
Eu gostaria de ter uma configuração de propriedades que pode, em certos ambientes, substituir propriedades específicas. Por exemplo, nossas propriedades JDBC padrão para o dev são:
db.driverClassName = com.mysql.jdbc.Driverdb.url = jdbc: mysql: // localhost: 3306 / ourdbdb.username = rootdb.password =O problema é que alguns de nossos desenvolvedores gostariam de ter um nome de usuário / senha diferente no banco de dados, ou possivelmente até mesmo um banco de dados não hospedado localmente. O mesmo é verdadeiro para a configuração do rabbitMQ, que atualmente usa uma configuração localhost / guest / guest semelhante. Ser capaz de substituir as propriedades de determinados elementos dessa configuração em uma base por desenvolvedor nos permitiria mover grande parte dos requisitos de infraestrutura / instalação para construir o software fora da máquina local e em servidores dedicados.
Eu configurei um projeto simples para envolver minha cabeça em torno da configuração necessária para alcançar o que eu quero, e esta é a minha primeira incursão no mundo da configuração de propriedades de mola, já que até agora, o carregamento e gerenciamento de propriedades é feito com alguns código. Aqui está minha configuração:
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 + "'.");
}
}
E minha configuração:
@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;
}
}
E para completude, meu dev.main.properties e test.main.properties:
main.property=dev
main.property=test
O principal problema é que recebo uma exceção de argumento ilegal. Tanto quanto eu posso dizer, o que eu escrevi deve ser o equivalente a javaconfig deste método:http://taidevcouk.wordpress.com/2013/07/04/overriding-a-packaged-spring-application-properties-file-via-an-external-file/ Infelizmente recebo o seguinte erro: java.lang.IllegalArgumentException: Não foi possível resolver o espaço reservado 'main.property' no valor da string "$ {main.property}". Note que eu também preciso cuidar do caso onde não há sub-ambiente, e este é o caso que eu comecei com (embora eu recebo o mesmo erro, mesmo se ambos os arquivos existirem). Se eu remover o bean que configura o segundo propertysourcesplaceholderconfigurer, então tudo funciona bem (o que significa que dev.main.properties é carregado e "E a propriedade é: 'dev'." É impressa).
Um problema secundário é que o código não parece ótimo, e cada camada do sistema precisará de dois setups do PSPC para poder acessar essas propriedades. Além disso, requer muitas chamadas manuais para System.getProperty (), uma vez que não consegui passar $ {spring.profiles.active} para PSPC.setLocation ();
Nota: Eu tentei @PropertySources ({primaryproperties, secondaryProperties}), mas isso falha porque secondaryProperties não existe. Eu também tentei o ambiente @Autowired Environment; e obtendo as propriedades disso, mas o PSPC secundário faz com que o ambiente não seja autowired ...
Então, seguindo essa longa explicação, minhas perguntas são:
É este o caminho certo para resolver este problema?Se sim, o que há de errado com minha configuração?Como posso simplificar a configuração (se em tudo)?Existe um mecanismo alternativo disponível que solucionaria o meu problema?Obrigado pelo seu tempo! :)