一、@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默认的过滤规则是开启的,如果我们要自定义的话是要关闭的;

ComponentScan相关推荐

  1. 在SpringBoot启动类上添加ComponentScan出现springbootapplication already applies given @ComponentScan

    查看@SpringBootApplication注解源码,可以看到 @SpringBootApplication=@Configuration+@EnableAutoConfiguration+@Co ...

  2. component-scan和annotation-driven

    <context:component-scan/> 该xml配置作用是启动Spring的组件扫描功能,自动扫描base-package指定的包及其子文件下的java文件,如果扫描到有@co ...

  3. Spring component-scan类扫描加载过程

    2019独角兽企业重金招聘Python工程师标准>>> https://github.com/javahongxi 有朋友最近问到了spring加载类的过程,尤其是基于annotat ...

  4. Spring配置中context:annotation-config VS context:component-scan

    Spring 中在使用注解(Annotation)会涉及到< context:annotation-config> 和 < context:component-scan>配置, ...

  5. SpringBoot—— @ComponentScan

    2019独角兽企业重金招聘Python工程师标准>>> SpringBoot在写启动类的时候如果不使用@ComponentScan指明对象扫描范围,默认指扫描当前启动类所在的包里的对 ...

  6. springboot 启动类注解 @SpringBootApplication 和 @ComponentScan 的问题

    问题: 在启动类Application上使用@ComponentScan 这个注解来扫描第三方的包,然后就会出现报错,异常就是无法加载本地的某些类,例如某些Dao无法注入. 分析: 启动类注解 @Sp ...

  7. Spring context:component-scan代替context:annotation-config

    Spring context:component-scan代替context:annotation-config XML: <?xml version="1.0" encod ...

  8. 组件注册——@ComponentScan自动扫描组件指定扫描规则

    包扫描.只要标注了@Controller.@Service.@Repository,@Component IOCTest.java package com.atguigu.test;import or ...

  9. Spring的新注解——Configuration、ComponentScan、Bean、Import、PropertySource || spring整合Junit分析

    spring中的新注解 spring整合Junit分析 1.应用程序的入口       main方法 2.junit单元测试中,没有main方法也能执行     junit集成了一个main方法    ...

  10. spring源码分析之context:component-scan/vsannotation-config/

    1.<context:annotation-config/> xsd中说明: <xsd:element name="annotation-config"> ...

最新文章

  1. 运用Hibernate-Tools自动生成Java类和schema时,出现not found while looking for property...异常...
  2. leetcode 216. 组合总和 III 思考分析
  3. 小甲鱼 OllyDbg 教程系列 (十) : Windows 逆向常用 api 以及 XOFTSPY 逆向
  4. python 网络维护_python学习之网络基础
  5. 阿里云linux主机更新hostname
  6. IT小公司避坑及生存指南
  7. DirectShow简介
  8. 机组0:为什么补码比原码多一个-128清晰解释
  9. Kubernetes init 提示 [ERROR ImagePull]: failed to pull image registry.aliyuncs.com/google_containers/c
  10. TR CEV65M-01460一个人,也有春夏秋冬
  11. CAD的那些装逼技巧!
  12. 【Java 数据结构】Map和Set
  13. 斐讯n1盒子装网易音乐命令版
  14. JavaScript - 语言基础
  15. Python读取键盘输入到一维列表及二维列表
  16. 前端程序员和后端程序员有什么不同?我来告诉你薪资待遇差多少
  17. iOS中几种数据持久化方案-转自简书
  18. GROUP BY无法运行解决办法
  19. “您可能是软件盗版的受害者”的解决方法
  20. 云原生服务网格Istio:原理、实践、架构与源码解析

热门文章

  1. onclick 阻止冒泡
  2. Python 直连打印机打印,可排版设置字体,附标签贴打印案例。
  3. Matlab:矩阵分解
  4. DECANTeR: DEteCtion of Anomalous outbouNd HTTP TRaffic by Passive Application Fingerprinting
  5. 九联UNT402A_S905L_S905L3通刷版线刷固件包及优盘刷机包
  6. 扫地僧Backtrader给力教程:量化回测核心篇(全集)
  7. html全排列,JavaScript全排列的六种算法 具体实现
  8. TI AM3552开发板(arm cortex A8) 初体验
  9. 左耳听风ARTS第2周
  10. OpenMMLab AI实战营第二期|人体关键点检测与MMPose学习笔记