【spring】@ComponentScan详解&@SpringBootApplication的scanBasePackages属性

文章目录

  • 1. 作用
  • 2. @ComponentScan源码
  • 3. SpringBootApplicatioscan中的scanBasePackages属性
  • 4. 注意事项
    • 4.1 Spring Boot项目
    • 4.2 非 Spring Boot项目

1. 作用

创建一个配置类,在配置类JavaConfig形式上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类,相当于之前的

参见 《JavaConfig、@Configuration、@ComponentScan入门例子》

2. @ComponentScan源码

@ComponentScan 的作用就是根据定义的扫描路径,把符合扫描规则的类装配到spring容器中,注解定义如下:

package org.springframework.context.annotation;

@Retention(RetentionPolicy.RUNTIME)
//表示只可以声明在类上
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    @AliasFor("basePackages")
    String[] value() default {};
 
    @AliasFor("value") //表示和value等价
    String[] basePackages() default {};
 
    Class<?>[] basePackageClasses() default {};
 
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;


  • @Target({ElementType.TYPE}) 表示只可以声明在类上

  • value 表示用法如 @ComponentScan(value="")
    也可以简写为 @ComponentScan("") ,省略value=

  • basePackages,表示用法如@ComponentScan(basePackages=""),由于和value等价(@AliasFor("value")),也可简写为@ComponentScan("")

  • nameGenerator: bean的名称的生成器

  • useDefaultFilters: 是否开启对@Component,@Repository,@Service,@Controller的类进行检测

  • includeFilters: 包含的过滤条件

    • FilterType.ANNOTATION:按照注解过滤

    • FilterType.ASSIGNABLE_TYPE:按照给定的类型

    • FilterType.ASPECTJ:使用ASPECTJ表达式

    • FilterType.REGEX:正则

    • FilterType.CUSTOM:自定义规则

  • excludeFilters: 排除的过滤条件,用法和includeFilters一样

一个稍完整的示例:

// com.jiaobuchong.business 和 com.jiaobuchong.user.servic 下的类都不会被扫描
@ComponentScan(basePackages = {"com.jiaobuchong.order.service"},
        excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX,
                pattern = "com.jiaobuchong.business\\..*"),
                @ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.jiaobuchong.user.service\\..*")})

3. SpringBootApplicatioscan中的scanBasePackages属性

本质上,SpringBootApplicatioscan中的scanBasePackages属性底层原理正是复用了@ComponentScan,因此语法和意义基本一致

...
public @interface SpringBootApplication {
   //复用了@ComponentScan
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};

@AliasFor标签表示别名的意义,可以理解为等价于

因此,下面2种用法相同:

@SpringBootApplication (scanBasePackages="com.test")
public class MyClass {

package com.test;
@ComponentScan("com.test")
@SpringBootApplication
public class MyClass {

4. 注意事项

4.1 Spring Boot项目

当使用Spring Boot项目时,可以不指定加载路径,即不使用@ComponentScan或@SpringBootApplication (scanBasePackages="com.test"),默认会加载MyClass所在的包

举个例子,看下面定义的类:

package com.test;
@SpringBootApplication
public class MyClass {

MyClass 的package为com.test,这个类使用了@SpringBootApplication注解,该注解定义了Spring将自动扫描包com.test及其子包下的bean。

如果你项目中所有的类都定义在com.demo.springboot包及其子包下,那你不需要做任何事。

但假如你一个类定义在包com.test2下,则你需要将这个新包也纳入扫描的范围,有两个方案可以达到这个目的:

  • 方案1, 定义@CoponentScan(“com”)

    这么做扫描的范围扩大到整个父包com

  • 方案2, 定义分别扫描两个包
    @ComponentScan({“com.test”,”com.test2”})

4.2 非 Spring Boot项目

在非Spring Boot项目中,我们必须显式地使用@ComponentScan注解定义被扫描的包,可以通过XML文件在应用上下文中定义或在Java代码中对应用上下文定义,否则会加载不到预期的bean。


参考:
《@ComponentScan 详解》 列出了具体参数的用法

《Spring注解——使用@ComponentScan自动扫描组件》 包含讲解和例子
《Spring和SpringBoot中的@Component 和@ComponentScan注解用法介绍和注意事项》

你可能感兴趣的:(spring,ComponentScan,SpringBoot,Application)