Digitalização de componentes Spring

Digitalização de componentes Spring

1. Visão geral

Neste tutorial, vamos cobrir a varredura de componentes no Spring. Ao trabalhar com o Spring, podemos anotar nossas classes para transformá-las em beans Spring. Mas, além disso,we can tell Spring where to search for these annotated classes, visto que nem todos eles devem se tornar beans nesta execução particular.

Obviamente, existem alguns padrões para a verificação de componentes, mas também podemos personalizar os pacotes para pesquisa.

Primeiro, vamos dar uma olhada nas configurações padrão.

2. @ComponentScan sem argumentos

2.1. Usando@ComponentScan em um aplicativo Spring

Com a Primavera,we use the @ComponentScan annotation along with @Configuration annotation to specify the packages that we want to be scanned. @ComponentScan sem argumentos diz ao Spring para examinar o pacote atual e todos os seus subpacotes.

Digamos que temos o seguinte@Configuration no pacotecom.example.componentscan.springapp:

@Configuration
@ComponentScan
public class SpringComponentScanApp {
    private static ApplicationContext applicationContext;

    @Bean
    public ExampleBean exampleBean() {
        return new ExampleBean();
    }

    public static void main(String[] args) {
        applicationContext =
          new AnnotationConfigApplicationContext(SpringComponentScanApp.class);

        for (String beanName : applicationContext.getBeanDefinitionNames()) {
            System.out.println(beanName);
        }
    }
}

Além disso, digamos que temos os componentesCateDog no pacotecom.example.componentscan.springapp.animals:

package com.example.componentscan.springapp.animals;
// ...
@Component
public class Cat {}
package com.example.componentscan.springapp.animals;
// ...
@Component
public class Dog {}

E, finalmente, temos o componenteRose no pacotecom.example.componentscan.springapp.flowers:

package com.example.componentscan.springapp.flowers;
// ...
@Component
public class Rose {}

A saída do métodomain() conterá todos os beans do pacotecom.example.componentscan.springapp e de seus subpacotes:

springComponentScanApp
cat
dog
rose
exampleBean

Observe que a classe do aplicativo principal também é um bean, pois é anotada com@Configuration,, que é um@Component.

Além disso, observe que a classe principal do aplicativo e a classe de configuração não são necessariamente as mesmas. Se eles forem diferentes, não importa onde colocar a classe do aplicativo principal. Only the location of the configuration class matters as component scanning starts from its package by default.

Finalmente, observe que em nosso exemplo@ComponentScan é equivalente a:

@ComponentScan(basePackages = "com.example.componentscan.springapp")

onde o argumentobasePackages é um pacote ou uma série de pacotes para varredura.

2.2. Usando@ComponentScan em um aplicativo Spring Boot

O truque com o Spring Boot é que muitas coisas acontecem implicitamente. Usamos a anotação@SpringBootApplication, mas é apenas uma combinação de três anotações:

@Configuration
@EnableAutoConfiguration
@ComponentScan

Vamos criar uma estrutura semelhante no pacotecom.example.componentscan.springbootapp. Desta vez, o aplicativo principal será:

package com.example.componentscan.springbootapp;
// ...
@SpringBootApplication
public class SpringBootComponentScanApp {
    private static ApplicationContext applicationContext;

    @Bean
    public ExampleBean exampleBean() {
        return new ExampleBean();
    }

    public static void main(String[] args) {
        applicationContext = SpringApplication.run(SpringBootComponentScanApp.class, args);
        checkBeansPresence(
          "cat", "dog", "rose", "exampleBean", "springBootComponentScanApp");

    }

    private static void checkBeansPresence(String... beans) {
        for (String beanName : beans) {
            System.out.println("Is " + beanName + " in ApplicationContext: " +
              applicationContext.containsBean(beanName));
        }
    }
}

Todos os outros pacotes e classes permanecem os mesmos, vamos apenas copiá-los para o pacotecom.example.componentscan.springbootapp próximo.

O Spring Boot verifica os pacotes de maneira semelhante ao nosso exemplo anterior. Vamos verificar o resultado:

Is cat in ApplicationContext: true
Is dog in ApplicationContext: true
Is rose in ApplicationContext: true
Is exampleBean in ApplicationContext: true
Is springBootComponentScanApp in ApplicationContext: true

O motivo pelo qual estamos apenas verificando a existência dos beans em nosso segundo exemplo (ao contrário de imprimir todos os beans), é que a saída seria muito grande.

Isso ocorre por causa da anotação@EnableAutoConfiguration implícita, que faz com que o Spring Boot crie muitos beans automaticamente, contando com as dependências no arquivopom.xml.

3. @ComponentScan com argumentos

Agora vamos personalizar os caminhos para digitalização. Por exemplo, digamos que queremos excluir o beanRose.

3.1. @ComponentScan para pacotes específicos

Podemos fazer isso de algumas maneiras. Primeiro, podemos mudar o pacote base:

@ComponentScan(basePackages = "com.example.componentscan.springapp.animals")
@Configuration
public class SpringComponentScanApp {
   // ...
}

Agora a saída será:

springComponentScanApp
cat
dog
exampleBean

Vamos ver o que está por trás disso:

  • springComponentScanApp é criado porque é uma configuração passada como um argumento para oAnnotationConfigApplicationContext

  • exampleBean é um bean configurado dentro da configuração

  • cat edog estão no pacotecom.example.componentscan.springapp.animals especificado

Todas as personalizações listadas acima também são aplicáveis ​​no Spring Boot. Podemos usar@ComponentScan junto com@SpringBootApplicatione o resultado será o mesmo:

@SpringBootApplication
@ComponentScan(basePackages = "com.example.componentscan.springbootapp.animals")

3.2. @ComponentScan com exclusões

Outra maneira é usar um filtro, especificando o padrão para as classes excluir:

@ComponentScan(excludeFilters =
  @ComponentScan.Filter(type=FilterType.REGEX,
    pattern="com\\.example\\.componentscan\\.springapp\\.flowers\\..*"))

Também podemos escolher um tipo de filtro diferente, comothe annotation supports several flexible options for filtering the scanned classes:

@ComponentScan(excludeFilters =
  @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = Rose.class))

4. O Pacote Padrão

Devemos evitar colocar a classe@Configurationin the default package (ou seja, não especificando o pacote). Nesse caso, o Spring varre todas as classes em todos os jarros em um caminho de classe. Isso causa erros e provavelmente o aplicativo não inicia.

5. Conclusão

Neste artigo, aprendemos quais pacotes o Spring verifica por padrão e como personalizar esses caminhos.

Como de costume, o código completo está disponívelover on GitHub.