Spring boot hits the jar and scans the Bean under the jar package

<!-- jar plug-in unit -->  
         <plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-jar-plugin</artifactId>  
            <version>2.4</version>  
            <configuration>  
                <archive>  
                    <manifest>  
                        <addDefaultImplementationEntries>true</addDefaultImplementationEntries>  
                    </manifest>  
                </archive>  
            </configuration>  
        </plugin>
@SpringBootApplication(scanBasePackages={"com.xql.config","com.xql.utils","com.xql.payutils"})
@MapperScan(basePackages = {"com.xql.payutils.dao"})
public class PayutilsApplication {

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

}


The reasons are as follows:

1. About Spring Boot automatic injection and component scanning

When using Spring Boot at ordinary times, annotations such as @ Configuration,@Contoller,@Service,@Component, etc. are often used. The classes added with these annotations will be automatically managed by the Spring container when Spring Boot is started.

As mentioned above, classes with some annotations will be loaded into the Spring Boot container when the Spring Boot container starts. Then, the function of component scanning is to assemble the classes that meet the scanning rules into the spring container according to the defined scanning path when Spring Boot is started.

2. @ ComponentScan in spring boot

This paper briefly introduces the basic functions of @ ComponentScan. This annotation provides us with some customizable configuration properties. Let's take a look at the @ ComponentScan annotation source code:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
  	// Specifies the location of the scanned package (the same as the basePackages attribute). It can be a single path or an array of scanned paths
    @AliasFor("basePackages")
    String[] value() default {};
	// Specify the location of the scanning package (same as: value attribute)
    @AliasFor("value")
    String[] basePackages() default {};
	// Specifies the specific scanned class
    Class<?>[] basePackageClasses() default {};
	// Generator for the name of the bean	
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
	// Control the class files that meet the component detection conditions. The default is * * / *. Class under package scanning
    String resourcePattern() default "**/*.class";
    // Enable detection of @ Component, @ Repository, @ Service, @ Controller classes
    boolean useDefaultFilters() default true;
    // Filter conditions included
    // 1. FilterType.ANNOTATION:  			 Filter by annotation
    // 2. FilterType.ASSIGNABLE_TYPE:  	     According to the given type
    // 3. FilterType.ASPECTJ:  				 Using AspectJ expressions
    // 4. FilterType.REGEX:  					 regular
    // 5. FilterType.CUSTOM:  				 Custom rules
    ComponentScan.Filter[] includeFilters() default {};
    // The usage of excluded filter conditions is the same as that of includeFilters
    ComponentScan.Filter[] excludeFilters() default {};

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;
        @AliasFor("classes")
        Class<?>[] value() default {};
        @AliasFor("value")
        Class<?>[] classes() default {};
        String[] pattern() default {};
    }
}

To summarize, the common methods of @ ComponentScan are as follows:

Specify the scanning range by using the value and basePackages attributes;
Add @ Controller, @ Service, @ Repository, @ Component annotations to the Spring container under the customized scanning path
Add classes without the above annotations in the scan path through includeFilters to the spring container
Filter out classes that do not need to be added to the spring container through excludeFilters
Customize the annotation method of adding @ Component annotation

3. Spring Boot @ SpringBootApplication

After the Spring Boot project is created, the @ SpringBootApplication annotation will be added to the default startup class. This annotation helps us turn on some automatic configuration functions by default, such as Java based Spring configuration, component scanning, especially the automatic configuration function for enabling Spring Boot.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration                    // Allow automatic configuration
@ComponentScan(
    excludeFilters = {@Filter(              // Define exclusion rules
    type = FilterType.CUSTOM,               // In a customized way
    classes = {TypeExcludeFilter.class}     // Custom implementation logic
), @Filter(                                 // ditto
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    
    // Add exclude rule for @ EnableAutoConfiguration
    @AliasFor(
        annotation = EnableAutoConfiguration.class,
        attribute = "exclude"
    )
    Class<?>[] exclude() default {};
    
    // Add excludeName rule for @ EnableAutoConfiguration
    @AliasFor(
        annotation = EnableAutoConfiguration.class,
        attribute = "excludeName"
    )
    String[] excludeName() default {};
    
    // Add basePackages rule for @ ComponentScan
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};

    // Add basepackageclass rule for @ ComponentScan
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};
}

As can be seen from the source code above, @ SpringBootApplication is a composite annotation, which is equivalent to using a @ SpringBootApplication instead of @ SpringBootConfiguration, @ EnableAutoConfiguration, @ ComponentScan.

Note: this note is from SpringBoot 1.2 Start offering, which means that if you are running a lower version, and if you need these features, you need to add them manually@Configuration´╝î@CompnentScan and@EnableAutoConfiguration. 

Then, there may be such a problem. I just used an @ SpringBootApplication annotation, but how can I customize the properties of @ ComponentScan?

Of course, the Spring team has well solved this problem by adding the @ AliasFor annotation to the attributes in the @ SpringBootApplication annotation class, so as to customize the attributes of the corresponding annotation by customizing the attributes in @ SpringBootApplication.

@AliasFor(
    annotation = ComponentScan.class,
    attribute = "basePackages"
)
String[] scanBasePackages() default {};

This code is the implementation. Through the attribute scanBasePackages of @ SpringBootApplication, you can customize the attribute basePackages in @ ComponentScan.

@AliasFor

In Spring annotations, it is often found that different attributes of many annotations play the same role, such as the value attribute and basePackages attribute of @ ComponentScan. Therefore, some basic restrictions need to be made when using. For example, the values of value and basePackages cannot conflict. For example, if you set the value or the value of basePackages attribute arbitrarily, you can obtain the value through another attribute, and so on. To handle these situations in a unified way, Spring created the @ AliasFor tag.

Tags: Java Spring Spring Boot

Posted on Fri, 26 Nov 2021 00:54:27 -0500 by macinslaw