Criando um Starter personalizado com Spring Boot
1. Visão geral
Os desenvolvedores principaisSpring Boot fornecemstarters para a maioria dos projetos de código aberto populares, mas não estamos limitados a eles.
We can also write our own custom starters. Se tivermos uma biblioteca interna para uso em nossa organização, seria uma boa prática também escrever um iniciador para ela se for usada no contexto do Spring Boot.
Esses iniciantes permitem que os desenvolvedores evitem configurações demoradas e iniciem rapidamente seu desenvolvimento. No entanto, com muitas coisas acontecendo em segundo plano, às vezes fica difícil entender como uma anotação ou apenas incluir uma dependência empom.xml permite tantos recursos.
Neste artigo, vamos desmistificar a mágica do Spring Boot para ver o que está acontecendo nos bastidores. Em seguida, usaremos esses conceitos para criar um iniciador para nossa própria biblioteca personalizada.
2. Desmistificando a configuração automática do Spring Boot
2.1. Aulas de configuração automática
Quando o Spring Boot é inicializado, ele procura um arquivo chamadospring.factories no caminho de classe. Este arquivo está localizado no diretórioMETA-INF. Vejamos um snippet deste projetofile from the spring-boot-autoconfigure:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
Esse arquivo mapeia um nome para diferentes classes de configuração que o Spring Boot tentará executar. Portanto, de acordo com esse trecho, o Spring Boot tentará executar todas as classes de configuração para RabbitMQ, Cassandra, MongoDB e Hibernate.
A execução ou não dessas classes dependerá da presença de classes dependentes no caminho de classe. Por exemplo, se as classes do MongoDB forem encontradas no classpath,MongoAutoConfiguration será executado e todos os beans relacionados ao mongo serão inicializados.
Esta inicialização condicional é habilitada pela anotação@ConditionalOnClass. Vejamos o snippet de código da classeMongoAutoConfiguration para ver seu uso:
@Configuration
@ConditionalOnClass(MongoClient.class)
@EnableConfigurationProperties(MongoProperties.class)
@ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")
public class MongoAutoConfiguration {
// configuration code
}
Agora como - seMongoClient estiver disponível no classpath - esta classe de configuração será executada populando o Spring bean factory com umMongoClient inicializado com configurações padrão.
2.2. Propriedades personalizadas do arquivoapplication.properties
O Spring Boot inicializa os beans usando alguns padrões pré-configurados. Para substituir esses padrões, geralmente os declaramos no arquivoapplication.properties com algum nome específico. Essas propriedades são selecionadas automaticamente pelo contêiner Spring Boot.
Vamos ver como isso funciona.
No snippet de código paraMongoAutoConfiguration, a anotação@EnableConfigurationProperties é declarada com a classeMongoProperties que atua como o contêiner para as propriedades personalizadas:
@ConfigurationProperties(prefix = "spring.data.mongodb")
public class MongoProperties {
private String host;
// other fields with standard getters and setters
}
O prefixo mais o nome do campo formam os nomes das propriedades no arquivoapplication.properties. Portanto, para definirhost para MongoDB, só precisamos escrever o seguinte no arquivo de propriedade:
spring.data.mongodb.host = localhost
Da mesma forma, os valores para outros campos da classe podem ser definidos usando o arquivo de propriedades.
3. Criando um Starter Personalizado
Com base nos conceitos da seção 2, para criar um iniciador personalizado, precisamos escrever os seguintes componentes:
-
Uma classe de configuração automática para nossa biblioteca, juntamente com uma classe de propriedades para configuração personalizada.
-
Um inicialpom para trazer as dependências da biblioteca e do projeto de configuração automática.
Para demonstração, criamos umsimple greeting library que receberá uma mensagem de saudação para diferentes horários do dia como parâmetros de configuração e produzirá a mensagem de saudação. Também criaremos um exemplo de aplicativo Spring Boot para demonstrar o uso de nossos módulos de configuração automática e inicial.
3.1. O Módulo Autoconfigure
Chamaremos nosso módulo de configuração automática degreeter-spring-boot-autoconfigure. Este módulo terá duas classes principais, ou seja, GreeterProperties que habilitará a configuração de propriedades personalizadas por meio do arquivoapplication.properties eGreeterAutoConfiguartion que criará os beans para a bibliotecagreeter.
Vejamos o código de ambas as classes:
@ConfigurationProperties(prefix = "example.greeter")
public class GreeterProperties {
private String userName;
private String morningMessage;
private String afternoonMessage;
private String eveningMessage;
private String nightMessage;
// standard getters and setters
}
@Configuration
@ConditionalOnClass(Greeter.class)
@EnableConfigurationProperties(GreeterProperties.class)
public class GreeterAutoConfiguration {
@Autowired
private GreeterProperties greeterProperties;
@Bean
@ConditionalOnMissingBean
public GreetingConfig greeterConfig() {
String userName = greeterProperties.getUserName() == null
? System.getProperty("user.name")
: greeterProperties.getUserName();
// ..
GreetingConfig greetingConfig = new GreetingConfig();
greetingConfig.put(USER_NAME, userName);
// ...
return greetingConfig;
}
@Bean
@ConditionalOnMissingBean
public Greeter greeter(GreetingConfig greetingConfig) {
return new Greeter(greetingConfig);
}
}
Também precisamos adicionar um arquivospring.factories no diretóriosrc/main/resources/META-INF com o seguinte conteúdo:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.greeter.autoconfigure.GreeterAutoConfiguration
Na inicialização do aplicativo, a classeGreeterAutoConfiguration será executada se a classeGreeter estiver presente no caminho de classe. Se for executado com êxito, ele preencherá o contexto do aplicativo Spring com os beansGreeterConfigeGreeter lendo as propriedades por meio da classeGreeterProperties.
A anotação@ConditionalOnMissingBean garantirá que esses beans somente serão criados se ainda não existirem. Isso permite que os desenvolvedores substituam completamente os beans configurados automaticamente, definindo os seus próprios em uma das classes@Configuration.
3.2. Criandopom.xml
Agora vamos criar opom inicial que trará as dependências para o módulo de configuração automática e a biblioteca saudação.
De acordo com a convenção de nomenclatura, todos os iniciadores que não são gerenciados pela equipe principal do Spring Boot devem começar com o nome da biblioteca seguido pelo sufixo-spring-boot-starter. Portanto, chamaremos nosso iniciador degreeter-spring-boot-starter:
4.0.0
com.example
greeter-spring-boot-starter
0.0.1-SNAPSHOT
UTF-8
0.0.1-SNAPSHOT
1.5.2.RELEASE
org.springframework.boot
spring-boot-starter
${spring-boot.version}
com.example
greeter-spring-boot-autoconfigure
${project.version}
com.example
greeter
${greeter.version}
3.3. Usando o Starter
Vamos criargreeter-spring-boot-sample-app que usará o iniciador. Empom.xml, precisamos adicioná-lo como uma dependência:
com.example
greeter-spring-boot-starter
${greeter-starter.version}
O Spring Boot configurará tudo automaticamente e teremos um beanGreeter pronto para ser injetado e usado.
Vamos também alterar alguns dos valores padrão deGreeterProperties definindo-os no arquivoapplication.properties com o prefixoexample.greeter:
example.greeter.userName=example
example.greeter.afternoonMessage=Woha\ Afternoon
Finalmente, vamos usar o beanGreeter em nosso aplicativo:
@SpringBootApplication
public class GreeterSampleApplication implements CommandLineRunner {
@Autowired
private Greeter greeter;
public static void main(String[] args) {
SpringApplication.run(GreeterSampleApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
String message = greeter.greet();
System.out.println(message);
}
}
4. Conclusão
Neste tutorial rápido, focamos na implementação de um iniciador personalizado do Spring Boot e em como esses iniciantes, juntamente com o mecanismo de configuração automática - funcionam em segundo plano para eliminar muitas configurações manuais.
O código-fonte completo para todos os módulos que criamos neste artigo pode ser encontradoover on GitHub.