Spring深入理解之ComponentScan

一、概述

ComponentScan顾名思义包扫描,底层其实就可以通过递归算法+反射将其装载成bean来实现的,实在开发过程中,Spring已经帮我们实现好了,我们其实就可以直接使用XML或者注解的形式来进行业务处理。

二、@ComponentScan的作用

@ComponentScan注解有两个作用

作用一:扫描含有@Component,@Controller,@Service和@Repository的类,并将其注入到spring容器中。

作用二:扫描含有@Configuration的类,并使其生效。

分析:作用一相信大家都明白其含义,再次不在赘述。作用二举例说明,例如Config2可以扫描到config2_test目录,该目录下不仅含有@Component,@Controller,@Service和@Repository注解标注的四个类,还包含Config1配置类。Config1配置类,可以扫描到config1_test目录,并且里面还包含一个@Bean注解。

三、同一个配置类上多个@ComponentScan可能会报错

下面的配置类在我公司电脑的idea版本里是可以将config3_test目录下的所有类都注册到spring容器中,但是在我家里的电脑上以及另一个同事的电脑上会报编译期错误,代码运行也会出错。

四、@ComponentScans的使用

由于同一个类上直接写多个@ComponentScan可能会报错,因此建议使用@ComponentScans,它可以解决直接在一个配置类上写多个@ComponentScan在有些电脑或idea版本上报错的问题。




@ComponentScan 详解

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

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {@AliasFor("basePackages")String[] value() default {};@AliasFor("value")String[] basePackages() default {};Class<?>[] basePackageClasses() default {};Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;String resourcePattern() default "**/*.class";boolean useDefaultFilters() default true;ComponentScan.Filter[] includeFilters() default {};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 {};}
}

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一样

我的工程结构如下,测试对controller和service的扫描,其中HelloController没有加@Controller等任何注解,就是一个普通类。

修改配置类如下:应用默认的过滤器,扫描service包:

@Configuration
@ComponentScan(value = "com.xhx.spring.service",useDefaultFilters = true
)
public class MyConfig {}

系统注入了两个service进去

改成如下所示:HelloController所在的包的类也被扫描了进去

@Configuration
@ComponentScan(value = "com.xhx.spring.service",useDefaultFilters = true,basePackageClasses = HelloController.class
)
public class MyConfig {}

系统中会注入下面就给类

把默认的过滤器关掉,扫描带Controller注解的。

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

按照类的类型扫描,虽然HelloController没有加注解,但是被注入到了spring容器中

@Configuration
@ComponentScan(value = "com.xhx.spring",useDefaultFilters = false,includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {HelloController.class})}
)
public class MyConfig {}

自定义扫描过滤器

package com.xhx.spring.componentscan.config;import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;import java.io.IOException;public class MyTypeFilter implements TypeFilter {@Overridepublic boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {String className = metadataReader.getClassMetadata().getClassName();if(className.contains("Controller")){return true;}return false;}
}

修改配置类

@Configuration
@ComponentScan(value = "com.xhx.spring",useDefaultFilters = false,includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})}
)
public class MyConfig {}

输出结果:

输出spring容器中的bean的测试类:只过滤输出了名字中含有hello的类。

package com.xhx.spring.componentscan;import com.xhx.spring.componentscan.config.MyConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;@RunWith(SpringRunner.class)
@SpringBootTest
public class ComponentScanApplicationTests {@Testpublic void testLoads() {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);List<String> hello = Arrays.stream(context.getBeanDefinitionNames()).collect(Collectors.toList());hello.stream().filter(name->name.contains("hello")).peek(System.out::println).count();}}

Spring深入理解之ComponentScan___@ComponentScan 详解相关推荐

  1. Spring零配置之@Configuration注解详解

    转载自 Spring零配置之@Configuration注解详解 @Configuration介绍 Spring3.0之前要使用Spring必须要有一个xml配置文件,这也是Spring的核心文件,而 ...

  2. Spring生命周期Bean初始化过程详解

    Spring生命周期Bean初始化过程详解 Spring 容器初始化 Spring Bean初始化 BeanFactory和FactoryBean 源码分析 Bean的实例化 preInstantia ...

  3. Spring循环依赖和三级缓存详解

    Spring循环依赖和三级缓存详解 Spring在启动过程中,使用到了三个map,称为三级缓存 我们可以这样理解,假设,我们只有一个缓存容器,并且缓存是直接开放给用户可以调用的,如果将未完成赋值的Be ...

  4. Spring IoC源码:getBean 详解

    文章目录 Spring源码系列: 前言 正文 方法1:getObjectForBeanInstance 方法2:getObjectFromFactoryBean 方法3:doGetObjectFrom ...

  5. java注解式开发_JAVA语言之Spring MVC注解式开发使用详解[Java代码]

    本文主要向大家介绍了JAVA语言的Spring MVC注解式开发使用详解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. MVC注解式开发即处理器基于注解的类开发, 对于每一个定义的处 ...

  6. spring MVC请求处理类注解属性详解

    spring MVC请求处理类注解属性详解

  7. spring boot模板引擎thymleaf用法详解

    spring boot模板引擎thymleaf用法详解 Spring-boot支持FreeMarker.Thymeleaf.jsp.veocity 但是对freemarker和thymeleaf的支持 ...

  8. spring学习笔记03-spring-DI-依赖注入详解(通过xml配置文件来配置依赖注入)

    spring学习笔记03-spring-DI-依赖注入详解 1.概念 2.构造函数注入 3.set方法注入 4.集合的注入 需要被注入的实体对象 package com.itheima.service ...

  9. java图片填充父容器_java相关:spring的父子容器及配置详解

    java相关:spring的父子容器及配置详解 发布于 2020-5-26| 复制链接 本篇文章主要介绍了spring的父子容器及配置详解,详细的介绍了spring父子容器的概念.使用场景和用法,有兴 ...

最新文章

  1. java绘等高线图_Matplotlib中的极坐标等高线图
  2. 用纯JS做俄罗斯方块 - 简要思路介绍(1)
  3. steam你所在的国家不允许看到此内容_Steam德国屏蔽“仅限成人”标签 众多3A大作可能被禁...
  4. 新华三的背景_新华三集团与飞友科技签署战略合作协议,共赢智慧机场新时代...
  5. bootstrap弹出的模态框水平垂直居中的实现
  6. 如何更改Live Writer发布照片到不同相册
  7. maven配置aliyun仓库地址
  8. c语言编程齿轮模数选择,斜齿轮变位系数分配-C程序.doc
  9. Ubuntu下设置开机启动项
  10. 李彦宏计算机领域的贡献,李彦宏:AI让计算机懂得人、响应人的需求
  11. 华为云教程(云备份CBR)
  12. 计算机专业吐槽搞笑,大学里那些专业搞笑描述,简直太形象了!网友:逗死我了!...
  13. 15.unsafe类的CAS是怎么保证原子性的?
  14. python学习(BMR计算器)
  15. Python基于Flask框架实现视频直播,电脑桌面录屏web端展示,远程控制电脑
  16. DB2密码过期的解决办法-创建新密码
  17. vue使用videojs播放mu38
  18. wget 命令 简单使用
  19. 上下班通勤车辆实时定位查询小程序开发制作介绍
  20. leetcode算法题-390.消除游戏

热门文章

  1. php sql跳过前四条数据,mysql实现每组取前N条记录的sql,以及后续的组数据量限制...
  2. oracle不要重复记录,Oracle中去重复记录 不用distinct
  3. rad linux下安装mysql_Linux(CentOS或RadHat)下MySQL源码安装
  4. arm tbh_TBH的完整形式是什么?
  5. 编辑距离 dp_使用动态编程(DP)编辑距离
  6. 计算机应用基础专2020春,计算机应用基础(专)(专,2020春)(20200831130023).pdf
  7. linux内核计数函数,linux中的内核引用计数器
  8. 5中bug vue_苹果官网出BUG!这些都只要一两百元
  9. cpn tools查看运行时间_Jmeter在Linux下的运行测试
  10. mysql镜像远程连接_docker 创建mysql镜像,并成功进行远程连接