组件注册:@ComponentScan

@ComponentScan注解用于自动扫描并注册组件到Spring的bean容器中。默认扫描同一包下的配置类,可配置basePackages、basePackageClasses、过滤条件等。包括includeFilters和excludeFilters,支持按注解、类型、ASPECTJ表达式、正则和自定义规则进行过滤。可使用@ComponentScans定义多个扫描规则。

@ComponentScan主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中。在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类,相当于之前的 <context:component-scan>。@ComponentScan注解默认装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中。

例子:

在xml文件配置的方式,我们可以这样来进行配置:

在配置类里面写包扫描:

@Configuration
@ComponentScan(value="com.hlkj")
public class SpringConfig {
    @Bean
    public Person person() {
        return new Person("lisi",20);
    }
}

我们创建PersonController、PersonService、PersonDao这几个类,分别添加了@Controller@Service@Repository注解:

@Controller
public class PersonController {
}

@Service
public class PersonService {
}

@Repository
public class PersonDao {
}

单元测试:

@Test
public void test01() {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for (String name : definitionNames) {
        System.out.println(name);
    }
}

测试结果:

从上面的测试结果我们可以发现主配置类 SpringConfig 也是IOC容器里面的组件,也被纳入了IOC容器的管理;我们从@Configuration这个注解点进去就可以发现这个注解上也标注了@Component的这个注解,也纳入到IOC容器中作为一个组件。

@ComponentScan详细配置:

basePackages与value:  用于指定包的路径,进行扫描

basePackageClasses: 用于指定某个类的包的路径进行扫描

nameGenerator: bean的名称的生成器

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

includeFilters: 包含的过滤条件

            FilterType.ANNOTATION:按照注解过滤

            FilterType.ASSIGNABLE_TYPE:按照给定的类型

            FilterType.ASPECTJ:使用ASPECTJ表达式

            FilterType.REGEX:正则

            FilterType.CUSTOM:自定义规则

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

下面是includeFilters和excludeFilters的例子:

includeFilters和excludeFilters可以指定要排除哪些包或者是只包含哪些包来进行管理:里面传是一个Filter[]数组。

配置excludeFilters:

@Configuration
@ComponentScan(value = "com.hlkj", excludeFilters = {
        @ComponentScan.Filter(type= FilterType.ANNOTATION, classes = {Controller.class, Service.class})
    })
public class SpringConfig {
    @Bean
    public Person person() {
        return new Person("lisi",20);
    }
}
@Test
public void test02() {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for (String name : definitionNames) {
        System.out.println(name);
    }
}

测试结果如下:这个时候,personService、personController这两个组件就已经被排除掉了,不再被IOC容器给管理。

配置includeFilters:

@Configuration
@ComponentScan(value = "com.hlkj", includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
    }, useDefaultFilters = false)
public class SpringConfig {
    @Bean
    public Person person() {
        return new Person("lisi",20);
    }
}
@Test
public void test03() {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for (String name : definitionNames) {
        System.out.println(name);
    }
}

测试结果如下:只有一个bookController被纳入到IOC容器进行管理。

我们还可以用 @ComponentScans来定义多个扫描规则:里面是@ComponentScan规则的数组

 

注:@ComponentScan的常用方式

  • 自定扫描路径下边带有@Controller,@Service,@Repository,@Component注解加入spring容器

  • 通过includeFilters加入扫描路径下没有以上注解的类加入spring容器

  • 通过excludeFilters过滤出不用加入spring容器的类

  • 自定义增加了@Component注解的注解方式

  • @ComponentScan这个注解是可以重复定义的:来指定不同的扫描策略

在Spring Boot应用中,`@SpringBootApplication` 注解是一个组合注解,它实际上包含了 `@SpringBootConfiguration`、`@EnableAutoConfiguration` 和 `@ComponentScan` 三个注解的功能[^1]。因此,当开发者在同一启动类上显式地添加 `@ComponentScan` 时,会导致两者之间的包扫描行为发生冲突或覆盖。 具体来说,`@SpringBootApplication` 默认会扫描该注解所在启动类的当前包及其所有子包中的组件(如 `@Component`, `@Service`, `@Repository` 等)[^2]。而如果此时又手动添加了 `@ComponentScan`,则 Spring 会优先使用这个显式的 `@ComponentScan` 配置,并忽略 `@SpringBootApplication` 中内置的 `@ComponentScan` 设置[^4]。 这种情况下,如果 `@ComponentScan` 的配置没有正确包含启动类所在包或其子包,则可能导致某些组件未被扫描到,进而引发 Bean 创建失败等问题。例如,若自定义的 `@ComponentScan` 指定了特定的包路径,但这些路径不包括主启动类所在的包,则原本期望自动扫描组件可能不会被加载进 Spring 容器中[^5]。 为了解决这个问题,有以下几种做法: - **避免重复声明**:除非确实需要自定义额外的扫描路径,否则不需要也不应该再单独添加 `@ComponentScan`,因为 `@SpringBootApplication` 已经具备了这一功能。 - **合并扫描路径**:如果确实需要扩展扫描范围至其他模块或第三方 JAR 包,可以在 `@ComponentScan` 中同时指定原有包和新增包路径。例如: ```java @ComponentScan(basePackages = {"com.example.myapp", "com.thirdparty.lib"}) ``` 这样可以确保原有的组件仍然能够被正确扫描到[^4]。 - **检查包结构**:保证项目结构与扫描配置相匹配,即确认 `@ComponentScan` 或 `@SpringBootApplication` 所指定的扫描路径确实涵盖了所有需要注册为 Spring Bean 的类所在位置。 综上所述,在大多数标准 Spring Boot 应用场景下,推荐仅使用 `@SpringBootApplication` 而不另行加入 `@ComponentScan`,以防止不必要的配置复杂性和潜在的组件扫描问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值