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! :)

questionAnswers(2)

yourAnswerToTheQuestion