ComponentScan

news/2025/2/16 3:40:33/

一、@ComponentScan注解是什么

如果你理解了ComponentScan,你就理解了Spring是一个依赖注入(dependency injection)框架。所有的内容都是关于bean的定义及其依赖关系。
定义Spring Beans的第一步是使用正确的注解@Component或@Service或@Repository或者@Controller
但是,Spring不知道你定义了某个bean除非它知道从哪里可以找到这个bean
ComponentScan做的事情就是告诉Spring从哪里找到bean
由你来定义哪些包需要被扫描。一旦你指定了,Spring将会在被指定的包及其下级包中寻找bean
下面分别介绍在Spring Boot项目和非Spring Boot项目(如简单的JSP/Servlet或者Spring MVC应用)中如何定义@Component Scan

二、@ComponentScan注解的基本使用

1.Spring Boot项目

总结:

  • 如果你的其他包都在使用了@SpringBootApplication注解的main
    app所在的包及其下级包中,则你什么都不用做,SpringBoot会自动帮你把其他包都扫描了
  • 如果你有一些bean所在的包,不在main
    app的包及其下级包中,那么你需要手动加上@ComponentScan注解并指定那个bean所在的包

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

package com.demo.springboot;@SpringBootApplication
public class SpringbootApplication {public static void main(String[] args) {ApplicationContext applicationContext = SpringApplication.run(SpringbootApplication .class, args);for (String name : applicationContext.getBeanDefinitionNames()) {System.out.println(name);}}
}

类 SpringbootApplication 在com.demo.springboot包下,这个类使用了@SpringBootApplication注解,该注解定义了Spring将自动扫描包com.demo.springboot及其子包下的bean
如果你项目中所有的类都定义在com.demo.springboot包及其子包下,那你不需要做任何事
但假如你一个类定义在包com.demo.somethingelse下,则你需要将这个新包也纳入扫描的范围,有两个方案可以达到这个目的。

方案1
定义@CoponentScan(“com.demo”)
这么做扫描的范围扩大到整个父包com.demo

@ComponentScan(“com.demo”)
@SpringBootApplication
public class SpringbootApplication {

方案2
定义分别扫描两个包
@ComponentScan({“com.demo.springboot”,”com.demo.somethingelse”})

@ComponentScan({"com.demo.springboot","com.demo.somethingelse"})
@SpringBootApplication
public class SpringbootApplication {

特别注意一下:如果使用了方案2,如果仅仅只写@ComponentScan({"com.demo.somethingelse"})将导致com.demo.springboot包下的类无法被扫描到(框架原始的默认扫描效果无效了)

2.非Spring Boot项目

在非Spring Boot项目中,我们必须显式地使用@ComponentScan注解定义被扫描的包,可以通过XML文件在应用上下文中定义或在Java代码中对应用上下文定义

Java代码方式

@ComponentScan({"com.demo.package1","com.demo.package2"})
@Configuration
public class SpringConfiguration {

XML文件方式

<context:component-scan base-package="com.demo.package1, com.demo.package2"/>

三、@ComponentScan注解说明

@ComponentScan:会自动扫描包路径下面的所有被@Controller、@Service、@Repository、@Component 注解标识的类,然后装配到Spring容器中。

@ComponentScan的属性: value指定扫描的包,includeFilters包含那些过滤,excludeFilters不包含那些过滤,useDefaultFilters默认的过滤规则是开启的,如果我们要自定义的话是要关闭的。其中@Filters是一个过滤器的接口。

@Filters 指过滤规则,FilterType指定过滤的规则

            FilterType.ANNOTATION:按照注解FilterType.ASSIGNABLE_TYPE:按照给定的类型;FilterType.ASPECTJ:使用ASPECTJ表达式FilterType.REGEX:使用正则指定FilterType.CUSTOM:使用自定义规则)classes指定过滤的类

1.基本示例:

创建controller:

@Controller
public class UserController {
}

创建service:

@Service
public class UserService {
}

创建dao:

@Repository
public class UserDao {
}

添加启动类:

@Configuration
@ComponentScan(value = "com.spring.annotation")
public class ScanConfig {}

测试:

    @Testpublic void test02() {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ScanConfig.class);String[] beanDefinitionNames = context.getBeanDefinitionNames();for (String name : beanDefinitionNames) {System.out.println(name);}}

结果:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactoryscanConfig
annotationConfig
userController
userDao
userService

可以看到对应的实体类已经注入到容器中

2.过滤指定的注解进行注入

  • excludeFilters (排除过滤器)

@Configuration
@ComponentScan(value = "com.spring.annotation",excludeFilters = {@ComponentScan.Filter(type=FilterType.ANNOTATION,classes={Controller.class})
})
public class ScanConfig{}

@ComponentScan.Filter 指定了过滤器的规则,FilterType.ANNOTATION 表示按注解过滤,classes指定需要过滤的注解,Controller注解被排除,classes为数组可以指定多个,重新运行结果:

scanConfig
annotationConfig
userDao
userService

可以看到 原来的 userController 已经消失,说明没有被注入到容器中去

  • includeFilters (包含过滤器)

@Configuration
@ComponentScan(value="com.spring.annotation",
//        excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})}includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})},useDefaultFilters = false
)
public class ScanConfig {
}

运行结果:

scanConfig
userController

可以看到只有 被@controller注解的bean注入到容器中去。useDefaultFilters默认的过滤规则是开启的,如果我们要自定义的话是要关闭的;


http://www.ppmy.cn/news/533459.html

相关文章

@ComponentScan

ComponentScan 作用 ComponentScan用于批量注册bean。 这个注解会让spring扫描指定包及其子包中所有的类&#xff0c;得到一批类的数组&#xff0c;然后将满足过滤器条件的类作为bean注册到spring容器中。 常用参数 value&#xff1a;指定需要扫描的包 ComponentScan({ “xxx.…

CANopen是个啥?

CANopen是个啥&#xff1f; 一、CANopen协议的诞生和意义二、为什么选择CANopen 一、CANopen协议的诞生和意义 我个人的理解就是基于CAN BUS的上层应用协议&#xff0c;就好像有菜有锅有调料&#xff0c;不同的人做出来的菜是不一样的&#xff0c;CANopen就是希望建立一个应用标…

CAN接口简介

1.1 CAN总线介绍 顾名思义&#xff0c;CAN总线名称如下&#xff1a; 目前世界上绝大多数汽车制造厂商都采用CAN总线来实现汽车内部控制系统之间的数据通信。 CAN总线由CAN_H、CAN_L双绞线组成&#xff0c;通过差分电压传输信号&#xff0c;提高了抗干扰能力&#xff0c;保证…

CANoe (1)

CANifif(表达式&#xff09; 语句&#xff1b; if(表达式&#xff09;语句1&#xff1b; else 语句2&#xff1b;forfor&#xff08;<初始化>;<条件表达式>;<增量>) 语句&#xff1b;whilewhile(表达式&#xff09; 语句&#xff1b;do whiledo 循环体语句…

Canal学习

环境准备 MySQL搭建及binlog开启 MySQL搭建教程&#xff08;Windows10&#xff09;&#xff1a;https://blog.csdn.net/liwenyang1992/article/details/121513620 MySQL搭建教程&#xff08;Linux&#xff0c;包含MySQL5.7&#xff0c;Zookeeper&#xff0c;Kafka等&#xf…

1 CAN

一、起源 CAN总线&#xff0c;全称Controller Area Network&#xff0c;控制器局域网络&#xff0c;是由德国博世BOSCH公司于1986年专门为汽车行业开发的一种串行通信总线&#xff0c;BOSCH公司以研发生产汽车电子产品和提供汽车解决方案著称&#xff0c;直到现在也是汽车领域知…

pecan

https://segmentfault.com/a/1190000003718598 上一篇文章我们了解了一个巨啰嗦的框架&#xff1a;Paste PasteDeploy Routes WebOb。后来OpenStack社区的人受不了这么啰嗦的代码了&#xff0c;决定换一个框架&#xff0c;他们最终选中了Pecan。Pecan框架相比上一篇文章的…

CAN 简介

1. 目的 本文主要介绍一部分 CAN 协议层 。 2. CAN 简介 这里的内容参考的是 1991.9 的 2.0 版本的官方 CAN 规格书 。 2.1 概述 CAN (控制器局域网) 是一种串行通讯协议 &#xff0c;传输速度可达 1Mbit/s 。总线由单一可双向信号传送的通道组成 &#xff0c;但此通道的物理层…