Personalizando seu aplicativo com
@ConfigurationProperties
, como uma alternativa ao uso
@Value
.
No artigo
- Configurando e Alterando a Funcionalidade do Aplicativo Através do Application.properties Usando o ConfigurationProperties
- Integrando application.properties ao IDE
- Verificando configurações

As diferenças entre as duas abordagens são descritas aqui -
ConfigurationProperties vs. ValorNa foto acima, a principal composição e princípio de operação. Os componentes disponíveis do sistema, são componentes Spring, apenas classes, várias constantes, variáveis etc. podem ser especificados no arquivo application.properties e, mesmo no momento em que o ambiente de desenvolvimento o indicar, opções serão oferecidas, verificações feitas. Quando o aplicativo é iniciado, os valores indicados serão verificados quanto à conformidade com o tipo, restrições e, se tudo estiver satisfatório, o aplicativo será iniciado. Por exemplo, é muito conveniente configurar a funcionalidade do aplicativo a partir da lista de componentes disponíveis do Spring, abaixo mostrarei como.
Classe de propriedade
Para criar configurações de aplicativo usando o ConfigurationProperties, você pode começar com uma classe de propriedade. Na verdade, indica as propriedades, componentes do sistema que queremos configurar.
AppProperties.java @ConfigurationProperties(prefix = "demo") @Validated public class AppProperties { private String vehicle; @Max(value = 999, message = "Value 'Property' should not be greater than 999") private Integer value; private Map<String,Integer> contexts; private StrategyEnum strategyEnum; private Resource resource; private DemoService service; public String getVehicle() { return vehicle; } public void setVehicle(String vehicle) { this.vehicle = vehicle; } public Map<String, Integer> getContexts() { return contexts; } public void setContexts(Map<String, Integer> contexts) { this.contexts = contexts; } public StrategyEnum getStrategyEnum() { return strategyEnum; } public void setStrategyEnum(StrategyEnum strategyEnum) { this.strategyEnum = strategyEnum; } public Resource getResource() { return resource; } public void setResource(Resource resource) { this.resource = resource; } public DemoService getService() { return service; } public void setService(DemoService service) { this.service = service; } public Integer getValue() { return value; } public void setValue(Integer value) { this.value = value; } @Override public String toString() { return "MyAppProperties{" + "\nvehicle=" + vehicle + "\n,contexts=" + contexts + "\n,service=" + service + "\n,value=" + value + "\n,strategyEnum=" + strategyEnum + '}'; } }
Na classe prefix = "demo" será usado em application.properties, como um prefixo da propriedade.
Classe de aplicativo SpringApplication e projeto pom.xml @SpringBootApplication @EnableConfigurationProperties({AppProperties.class}) @ImportResource(value= "classpath:context.xml") public class DemoConfigProcessorApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(DemoConfigProcessorApplication.class, args); AppProperties properties = context.getBean(AppProperties.class); String perform = properties.getService().perform(properties.getVehicle()); System.out.println("perform: " + perform); System.out.println(properties.toString()); } }
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demoConfigProcessor</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demoConfigProcessor</name> <description>Demo project for Spring Boot Configuration Processor</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Então eu declarei duas caixas de mola
Contexto de primavera (context.xml) <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="service1" class="com.example.demoConfigProcessor.MyDemoService1"> <description>Description MyDemoService 1</description> </bean> <bean id="service2" class="com.example.demoConfigProcessor.MyDemoService2"> <description>Description MyDemoService 2</description> </bean> </beans>
Na classe AppProperties, indiquei um link para alguns serviços de aplicativos disponíveis, alterarei em application.properties, terei duas de suas implementações e conectarei uma delas em application.properties.

Aqui está a sua implementação
DemoService public interface DemoService { String perform(String value); }
public class MyDemoService1 implements DemoService { @Override public String perform(String value) { return "Service №1: perform routine maintenance work on <" + value +">"; } }
public class MyDemoService2 implements DemoService { @Override public String perform(String value) { return "Service №2: perform routine maintenance work on <" + value +">"; } }
Agora isso é suficiente para começar a customizar application.properties. Mas sempre que são feitas alterações na classe com o ConfigurationProperties, você precisa
recriar o projeto, após o qual o arquivo aparece no projeto
\target\classes\META-INF\spring-configuration-metadata.json
. Na verdade, seu IDE usa para edição no arquivo application.properties. Vou indicar sua estrutura no link nos materiais. Este arquivo será criado com base na classe AppProperties. Se agora você abrir o arquivo application.properties e começar a digitar “demo”, o ambiente começará a mostrar as propriedades disponíveis

Se você tentar digitar o tipo errado, o IDE reportará

Mesmo se você deixar como está e tentar iniciar o aplicativo, haverá um erro completamente distinto

Adicionando metadados adicionais
Metadados adicionais, isso é apenas para a conveniência de trabalhar com application.properties no IDE; se isso não for necessário, você não poderá fazê-lo. Para fazer isso, é possível especificar dicas e outras informações para o ambiente em um arquivo adicional. Para fazer isso, copie o arquivo spring-configuration-metadata.json criado para
\src\main\resources\META-INF\
e renomeie-o para
additional-spring-configuration-metadata.json
. Neste arquivo, estarei interessado apenas na seção de dicas: []
Nele será possível listar, por exemplo, valores válidos para demo.vehicle
"hints": [ { "name": "demo.vehicle", "values": [ { "value": "car make A", "description": "Car brand A is allowed." }, { "value": "car make B", "description": "Car brand B is allowed." } ] }]
No campo "nome", a propriedade "demo.vehicle" é indicada e, em "valores", uma lista de valores válidos. Agora, se eu reconstruir o projeto e for para o arquivo application.properties, quando digitar demo.vehicle, obtenho uma lista de valores válidos

Se você inserir um diferente do proposto, mas do mesmo tipo, o editor destacará, mas o aplicativo iniciará neste caso, pois essa não é uma restrição estrita, mas apenas uma dica.

No início do projeto, anunciei dois serviços MyDemoService1 e MyDemoService2, ambos implementam a interface DemoService, agora você pode configurar para que apenas os serviços que implementam essa interface sejam acessíveis a application.properties e, portanto, a classe selecionada seja inicializada na classe AppProperties. Para fazer isso, existem Provedores, você pode especificá-los em metadados adicionais da configuração da mola. Existem vários tipos de provedores que podem ser encontrados na documentação; mostrarei um exemplo para uma
spring-bean-reference
. Este tipo mostra os nomes dos beans disponíveis no projeto atual. A lista é limitada à classe base ou interface.
Exemplo de fornecedores para DemoService:
"hints": [ { "name": "demo.service", "providers": [ { "name": "spring-bean-reference", "parameters": { "target": "com.example.demoConfigProcessor.DemoService" } } ] } ]
Depois disso, em application.properties para o parâmetro demo.service, uma opção de dois serviços estará disponível, você poderá ver sua descrição (descrição da definição).

Agora é conveniente escolher o serviço certo, alterar a funcionalidade do aplicativo. Há um ponto para as configurações do objeto: o Spring precisa de uma ajudinha para converter a sequência especificada nas configurações em um objeto. Para fazer isso, uma pequena classe é herdada do Converter.
ServiceConverter @Component @ConfigurationPropertiesBinding public class ServiceConverter implements Converter<String, DemoService> { @Autowired private ApplicationContext applicationContext; @Override public DemoService convert(String source) { return (DemoService) applicationContext.getBean(source); } }
O diagrama de classe do projeto mostra como esses serviços são separados do aplicativo principal e acessíveis através do AppProperties.

Propriedade de validação
Nos campos da classe AppProperties, você pode adicionar verificações disponíveis na estrutura do JSR 303. Escrevi sobre isso
aqui . Isso resultará em um arquivo de configuração de aplicativo conveniente e verificável.
Saída do console

Estrutura do projeto

Arquivo completo additional-spring-configuration-metadata.json
metadados adicionais da configuração da mola { "groups": [ { "name": "demo", "type": "com.example.demoConfigProcessor.AppProperties", "sourceType": "com.example.demoConfigProcessor.AppProperties" } ], "properties": [ { "name": "demo.contexts", "type": "java.util.Map<java.lang.String,java.lang.Integer>", "sourceType": "com.example.demoConfigProcessor.AppProperties" }, { "name": "demo.vehicle", "type": "java.lang.String", "sourceType": "com.example.demoConfigProcessor.AppProperties" } ], "hints": [ { "name": "demo.vehicle", "values": [ { "value": "car make A", "description": "Car brand A is allowed." }, { "value": "car make B", "description": "Car brand B is allowed." } ] }, { "name": "demo.service", "providers": [ { "name": "spring-bean-reference", "parameters": { "target": "com.example.demoConfigProcessor.DemoService" } } ] } ] }
Materiais de
metadados de configuração