spring-boot

Package scanning

Introduction#

In this topic I will overview spring boot package scanning.

You can find some basic information in spring boot docs in the following link (using-boot-structuring-your-code) but I will try to provide more detailed information.

Spring boot, and spring in general, provide a feature to automatically scan packages for certain annotations in order to create beans and configuration.

Parameters#

Annotation Details
@SpringBootApplication Main spring boot application annotation. used one time in the application, contains a main method, and act as main package for package scanning
@SpringBootConfiguration Indicates that a class provides Spring Boot application. Should be declared only once in the application, usually automatically by setting @SpringBootApplication
@EnableAutoConfiguration Enable auto-configuration of the Spring Application Context. Should be declared only once in the application, usually automatically by setting @SpringBootApplication
@ComponentScan Used to trigger automatic package scanning on a certain package and its children or to set custom package scanning
@Configuration Used to declare one or more @Bean methods. Can be picked by auto package scanning in order to declare one or more @Bean methods instead of traditional xml configuration
@Bean Indicates that a method produces a bean to be managed by the Spring container. Usually @Bean annotated methods will be placed in @Configuration annotated classes that will be picked by package scanning to create java configuration based beans.
@Component By declaring a class as a @Component it becomes a candidates for auto-detection when using annotation-based configuration and classpath scanning. Usually a class annotated with @Component will become a bean in the application
@Repository Originally defined by Domain-Driven Design (Evans, 2003) as “a mechanism for encapsulating storage. It is usualy used to indicate a Repository for spring data
@Service Very similar in practice to @Component. originally defined by Domain-Driven Design (Evans, 2003) as “an operation offered as an interface that stands alone in the model, with no encapsulated state.”
@Controller Indicates that an annotated class is a “Controller” (e.g. a web controller).
@RestController A convenience annotation that is itself annotated with @Controller and @ResponseBody. Will be automatically picked by default because it contains the @Controller annotation that is picked by default.
## @SpringBootApplication
The most basic way to structure your code using spring boot for good automatic package scanning is using @SpringBootApplication annotation. This annotation provide in itself 3 other annotations that helps with automatic scanning: @SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan (more info about each annotation in the Parameters section).

@SpringBootApplication will usualy be placed in the main package and all other components will be placed in packages under this file:

com
 +- example
     +- myproject
         +- Application.java (annotated with @SpringBootApplication)
         |
         +- domain
         |   +- Customer.java
         |   +- CustomerRepository.java
         |
         +- service
         |   +- CustomerService.java
         |
         +- web
             +- CustomerController.java

Unless mentioned otherwise, spring boot detects @Configuration, @Component, @Repository, @Service, @Controller, @RestController annotations automatically under the scanned packages (@Configuration and @RestController are being picked because they are annotated by @Component and @Controller accordingly).

Basic Code example:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    
}

Setting packages/classes explicitly

Since version 1.3 you can also tell spring boot to scan specific packages by setting scanBasePackages or scanBasePackageClasses in @SpringBootApplication instead of specifying @ComponentScan.

  1. @SpringBootApplication(scanBasePackages = "com.example.myproject") - set com.example.myproject as the base package to scan.
  2. @SpringBootApplication(scanBasePackageClasses = CustomerController.class) - type-safe alternative to scanBasePackages sets the package of CustomerController.java, com.example.myproject.web, as the base package to scan.

Excluding auto-configuration

Another important feature is the ability to exclude specific auto-configuration classes using exclude or excludeName (excludeName exist since version 1.3).

  1. @SpringBootApplication(exclude = DemoConfiguration.class) - will exclude DemoConfiguration from auto package scanning.
  2. @SpringBootApplication(excludeName = "DemoConfiguration") - will do the same using class fully classified name.

@ComponentScan

You can use @ComponentScan in order to configure more complex package scanning. There is also @ComponentScans that act as a container annotation that aggregates several @ComponentScan annotations.

Basic code examples

@ComponentScan
public class DemoAutoConfiguration {
}

@ComponentScans({@ComponentScan("com.example1"), @ComponentScan("com.example2")})
public class DemoAutoConfiguration {
}

Stating @ComponentScan with no configuration acts like @SpringBootApplication and scans all packages under the class annotated with this annotation.

In this example I will state some of the useful attributes of @ComponentScan:

  1. basePackages - can be used to state specific packages to scan.
  2. useDefaultFilters - by setting this attribute to false (defaults true) you can make sure spring does not scan @Component, @Repository, @Service, or @Controller automatically.
  3. includeFilters - can be used to include specific spring annotations / regex patterns to include in package scanning.
  4. excludeFilters - can be used to exclude specific spring annotations / regex patterns to include in package scanning.

There are many more attributes but those are the most commonly used in order to customize package scanning.

Creating your own auto-configuration

Spring boot is based on a lot of pre-made auto-configuration parent projects. You should already be familiar with spring boot starter projects.

You can easily create your own starter project by doing the following easy steps:

  1. Create some @Configuration classes to define default beans. You should use external properties as much as possible to allow customization and try to use auto-configuration helper annotations like @AutoConfigureBefore, @AutoConfigureAfter, @ConditionalOnBean, @ConditionalOnMissingBean etc. You can find more detailed information on each annotation in the official documentation Condition annotations

  2. Place an auto-configuration file/files that aggregates all of the @Configuration classes.

  3. Create a file named spring.factories and place it in src/main/resources/META-INF.

  4. In spring.factories, set org.springframework.boot.autoconfigure.EnableAutoConfiguration property with comma separated values of your @Configuration classes:

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=
    com.mycorp.libx.autoconfigure.LibXAutoConfiguration,
    com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration

Using this method you can create your own auto-configuration classes that will be picked by spring-boot. Spring-boot automatically scan all maven/gradle dependencies for a spring.factories file, if it finds one, it adds all @Configuration classes specified in it to its auto-configuration process.

Make sure your auto-configuration starter project does not contain spring boot maven plugin because it will package the project as an executable JAR and won’t be loaded by the classpath as intended - spring boot will not be able to find your spring.factories and won’t load your configuration


This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow