Criando um Starter personalizado com Spring Boot

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:

  1. Uma classe de configuração automática para nossa biblioteca, juntamente com uma classe de propriedades para configuração personalizada.

  2. 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.