Propriedades com Spring e Spring Boot
1. Visão geral
Este tutorial mostrará como configurar e usarProperties in Spring - via configuração Java e@PropertySource ou via XML e<property-placeholder>,as well how properties work in Spring Boot.
Leitura adicional:
Guia de idiomas do Spring Expression
Este artigo explora o Spring Expression Language (SpEL), uma linguagem de expressão poderosa que oferece suporte à consulta e manipulação de gráficos de objetos em tempo de execução.
Configurar um aplicativo Web de inicialização Spring
Algumas das configurações mais úteis para um aplicativo Spring Boot.
Guia para @ConfigurationProperties no Spring Boot
Um guia rápido e prático para a anotação @ConfigurationProperties no Spring Boot.
2. Registrar um arquivo de propriedades por meio de anotações Java
O Spring 3.1 também apresentathe new @PropertySource annotation, como um mecanismo conveniente para adicionar fontes de propriedade ao ambiente. Esta anotação deve ser usada em conjunto com a configuração baseada em Java e a anotação@Configuration:
@Configuration
@PropertySource("classpath:foo.properties")
public class PropertiesWithJavaConfig {
//...
}
Outra maneira muito útil de registrar um novo arquivo de propriedades é usar um espaço reservado para permitirdynamically select the right file at runtime; por exemplo:
@PropertySource({
"classpath:persistence-${envTarget:mysql}.properties"
})
...
2.1. Definindo vários locais de propriedade
A anotação@PropertySource pode ser repetida emaccording to Java 8 conventions. Portanto, se estivermos usando Java 8 ou superior, podemos usar esta anotação para definir vários locais de propriedade:
@PropertySource("classpath:foo.properties")
@PropertySource("classpath:bar.properties")
public class PropertiesWithJavaConfig {
//...
}
Obviamente, também podemos usar a anotação@PropertySources e especificar um array de@PropertySource. Isso funciona em qualquer versão Java suportada, não apenas no Java 8 ou superior:
@PropertySources({
@PropertySource("classpath:foo.properties"),
@PropertySource("classpath:bar.properties")
})
public class PropertiesWithJavaConfig {
//...
}
Em qualquer caso, é importante notar quein the event of a property name collision, the last source read takes precedence.
3. Registrar um arquivo de propriedades em XML
Em XML, novos arquivos de propriedades podem ser disponibilizados ao Spring viathe <context:property-placeholder … > namespace element:
O arquivofoo.properties deve ser colocado em/src/main/resources para que esteja disponível no caminho de classe em tempo de execução.
No caso demultiple <property-placeholder> elements estarem presentes no contexto do Spring, existem algumas práticas recomendadas:
-
o atributoorder precisa ser especificado para corrigir a ordem em que são processados pelo Spring
-
todos os marcadores de posição de propriedade menos o último (order mais alto) devem terignore-unresolvable=”true” para permitir que o mecanismo de resolução passe para outros no contexto sem lançar uma exceção
3.1. Registrar vários arquivos de propriedades em XML
Na seção anterior, vimos como definir vários arquivos de propriedades usando anotações no Java 8 ou posterior. Da mesma forma, podemosdefine multiple properties files using XML configuration:
E, como antes,in the event of a property name collision, the last source read takes precedence.
4. Usando / Injetando Propriedades
Injecting a property with the @Value annotation é direto:
@Value( "${jdbc.url}" )
private String jdbcUrl;
A default value of the property também pode ser especificado:
@Value( "${jdbc.url:aDefaultUrl}" )
private String jdbcUrl;
Usando propriedades na configuração do Spring XML:
Ambos osPropertyPlaceholderConfigurer mais antigos e os novosPropertySourcesPlaceholderConfigurer adicionados no Spring 3.1resolve $\{…} placeholders dentro dos valores de propriedade de definição de bean e anotações@Value.
Finalmente - podemos obtain the value of a property using the Environment API:
@Autowired
private Environment env;
...
dataSource.setUrl(env.getProperty("jdbc.url"));
Uma advertência muito importante aqui é queusing <property-placeholder> will not expose the properties to the Spring Environment - isso significa que recuperar o valor assim não funcionará - ele retornaránull:
env.getProperty("key.something")
5. Propriedades com Spring Boot
Antes de entrarmos em opções de configuração mais avançadas para propriedades, vamos passar algum tempo olhandothe new properties support in Spring Boot.
De modo geral, este novo suporte envolveless configuration em relação ao Spring padrão, o que é, claro, um dos principais objetivos do Boot.
5.1. application.properties - o arquivo de propriedade padrão
A inicialização aplica sua convenção típica sobre a abordagem de configuração aos arquivos de propriedades. Isso significa que podemos simplesmente colocar um arquivo “application.properties” em nosso diretório “src/main/resources” e ele será detectado automaticamente. Podemos então injetar quaisquer propriedades carregadas dele normalmente.
Portanto, ao usar este arquivo padrão, não precisamos registrar explicitamente umPropertySource, ou mesmo fornecer um caminho para um arquivo de propriedade.
Também podemos configurar um arquivo diferente em tempo de execução, se necessário, usando uma propriedade de ambiente:
java -jar app.jar --spring.config.location=classpath:/another-location.properties
5.2. Arquivo de propriedades específicas do ambiente
Se precisarmos direcionar diferentes ambientes, há um mecanismo embutido para isso no Boot.
Podemos simplesmente definir um arquivo“application-environment.properties” no diretório“src/main/resources” - e então definir um perfil Spring com o mesmo nome de ambiente.
Por exemplo, se definirmos um ambiente de "teste", isso significa que teremos que definir um perfilstaginge entãoapplication-staging.properties.
Este arquivo env será carregado ewill take precedence over the default property file. Observe que o arquivo padrão ainda será carregado, mas quando há uma colisão de propriedades, o arquivo de propriedade específico do ambiente tem precedência.
5.3. Arquivo de propriedades específicas do teste
Também podemos ter a necessidade de usar diferentes valores de propriedade quando nosso aplicativo estiver em teste.
Spring Boot lida com isso olhando em nosso diretório “src/test/resources” durante uma execução de teste. Novamente, as propriedades padrão ainda serão injetáveis normalmente, mas serão substituídas por essas se houver uma colisão.
5.4. A anotação@TestPropertySource
Se precisarmos de um controle mais granular sobre as propriedades de teste, podemos usar a anotação@TestPropertySource.
Isso nos permite definir propriedades de teste para um contexto de teste específico, tendo precedência sobre as fontes de propriedades padrão:
@ContextConfiguration
@TestPropertySource("/my-test.properties")
public class IntegrationTests {
// tests
}
Se não quisermos usar um arquivo, podemos especificar nomes e valores diretamente:
@ContextConfiguration
@TestPropertySource("foo=bar", "bar=foo")
public class IntegrationTests {
// tests
}
Também podemos obter um efeito semelhante usando o argumentoproperties da anotação@SpringBootTest:
@SpringBootTest(properties = {"foo=bar", "bar=foo"})
public class IntegrationTests {
// tests
}
5.5. Propriedades Hierárquicas
Se tivermos propriedades que são agrupadas, podemos fazer uso da anotação@ConfigurationProperties que mapeará essas hierarquias de propriedades em gráficos de objetos Java.
Vamos pegar algumas propriedades usadas para configurar uma conexão de banco de dados:
database.url=jdbc:postgresql:/localhost:5432/instance
database.username=foo
database.password=bar
E então vamos usar a anotação para mapeá-los para um objeto de banco de dados:
@ConfigurationProperties(prefix = "database")
public class Database {
String url;
String username;
String password;
// standard getters and setters
}
Spring Boot aplica sua convenção sobre a abordagem de configuração novamente, mapeando automaticamente entre os nomes das propriedades e seus campos correspondentes. Tudo o que precisamos fornecer é o prefixo da propriedade.
Se você quiser se aprofundar nas propriedades de configuração, dê uma olhada emthe in-depth article.
5.6. Alternativa - Arquivos YAML
Arquivos YAML também são suportados.
As mesmas regras de nomenclatura se aplicam a arquivos de propriedades específicos de teste, específicos de ambiente e padrão. A única diferença é a extensão do arquivo e uma dependência da bibliotecaSnakeYAML estar em seu classpath.
YAML é particularmente bom para armazenamento de propriedades hierárquicas; o seguinte arquivo de propriedades:
database.url=jdbc:postgresql:/localhost:5432/instance
database.username=foo
database.password=bar
secret: foo
É sinônimo do seguinte arquivo YAML:
database:
url: jdbc:postgresql:/localhost:5432/instance
username: foo
password: bar
secret: foo
Também vale a pena mencionar que os arquivos YAML não suportam a anotação@PropertySource, portanto, se o uso da anotação fosse necessário, isso nos limitaria a usar um arquivo de propriedades.
5.7. Propriedades de argumentos de linha de comando
Ao contrário de usar arquivos, as propriedades podem ser transmitidas diretamente na linha de comando:
java -jar app.jar --property="value"
Você também pode fazer isso por meio das propriedades do sistema, que são fornecidas antes do comando-jar, e não depois dele:
java -Dproperty.name="value" -jar app.jar
5.8. Propriedades das variáveis de ambiente
O Spring Boot também detectará variáveis de ambiente, tratando-as como propriedades:
export name=value
java -jar app.jar
5.9 Randomization of Property Values
Se não quisermos valores de propriedade deterministas,RandomValuePropertySource pode ser usado para randomizar os valores das propriedades:
random.number=${random.int}
random.long=${random.long}
random.uuid=${random.uuid}
5.10. Tipos adicionais de fontes de propriedade
O Spring Boot suporta várias fontes de propriedades, implementando uma ordem bem pensada para permitir a substituição sensata. Vale a pena consultar oofficial documentation, que vai além do escopo deste artigo.
6. Configuração usando Raw Beans no Spring 3.0 - oPropertyPlaceholderConfigurer
Além dos métodos convenientes de obter propriedades no Spring - anotações e namespace XML - o bean de configuração de propriedade também pode ser definido e registradomanually. Trabalhar comPropertyPlaceholderConfigurer nos dá controle total sobre a configuração, com a desvantagem de ser mais prolixo e, na maioria das vezes, desnecessário.
6.1. Configuração Java
@Bean
public static PropertyPlaceholderConfigurer properties() {
PropertyPlaceholderConfigurer ppc
= new PropertyPlaceholderConfigurer();
Resource[] resources = new ClassPathResource[]
{ new ClassPathResource( "foo.properties" ) };
ppc.setLocations( resources );
ppc.setIgnoreUnresolvablePlaceholders( true );
return ppc;
}
6.2. Configuração XML
classpath:foo.properties
7. Configuração usando Raw Beans no Spring 3.1 - oPropertySourcesPlaceholderConfigurer
Da mesma forma, no Spring 3.1, o novoPropertySourcesPlaceholderConfigurer também pode ser configurado manualmente:
7.1. Configuração Java
@Bean
public static PropertySourcesPlaceholderConfigurer properties(){
PropertySourcesPlaceholderConfigurer pspc
= new PropertySourcesPlaceholderConfigurer();
Resource[] resources = new ClassPathResource[ ]
{ new ClassPathResource( "foo.properties" ) };
pspc.setLocations( resources );
pspc.setIgnoreUnresolvablePlaceholders( true );
return pspc;
}
7.2. Configuração XML
classpath:foo.properties
8. Propriedades em contextos pai-filho
Esta pergunta continua surgindo de novo e de novo - o que acontece quando seuweb application has a parent and a child context? O contexto pai pode ter algumas funcionalidades principais comuns e beans e, em seguida, um (ou vários) contextos filhos, talvez contendo beans específicos de servlet.
Nesse caso, qual é a melhor maneira de definir arquivos de propriedades e incluí-los nesses contextos? Além do mais, como recuperar melhor essas propriedades do Spring Aqui está a repartição simples.
8.1. Se o arquivo de propriedades for definido em XML com roperty-placeholder>
Se o arquivo fordefined in the Parent context:
-
@Value funciona emChild context: NÃO
-
@Value trabalha emParent context: SIM
Se o arquivo fordefined in the Child context:
-
@Value trabalha emChild context: SIM
-
@Value funciona emParent context: NÃO
Finalmente, como discutimos antes,<property-placeholder> não expõe as propriedades ao ambiente, então:
-
environment.getProperty funciona emeither context: NÃO
8.2. Se o arquivo de propriedades for definido em Java com@PropertySource
Se o arquivo fordefined in the Parent context:
-
@Value trabalha emChild context: SIM
-
@Value trabalha emParent context: SIM
-
environment.getProperty emChild context: SIM
-
environment.getProperty emParent context: SIM
Se o arquivo fordefined in the Child context:
-
@Value trabalha emChild context: SIM
-
@Value funciona emParent context: NÃO
-
environment.getProperty emChild context: SIM
-
environment.getProperty emParent context: NÃO
9. Conclusão
Este artigo mostra váriosexamples of working with properties and properties files in Spring.
Como sempre, todo o código que sustenta o artigo está disponívelover on Github. Este é um projeto baseado em Maven, portanto, deve ser fácil importar e executar como está.