二、Spring中的@ComponentScan自动扫描组件
在以往采用xml配置的方式中,我们通常需要配置<context:component-scan>
标签
比如这样:
<!-- 包扫描、只要标注了@Controller、@Service、@Repository,@Component -->
<context:component-scan base-package="com.atguigu"></context:component-scan>
那在javaConfig的配置方式中,对应于@ComponentScan
注解
我们现在就建一个例子 ,来具体演示一下。
我们web工程中,新建一个BookController
类,具体如下:
package com.atguigu.controller;
// 省略了包的导入
@Controller
public class BookController {
@Autowired
private BookService bookService;
}
BookService
类
package com.atguigu.service;
@Service
public class BookService {
@Autowired
private BookDao bookDao;
public void print(){
System.out.println(bookDao);
}
@Override
public String toString() {
return "BookService [bookDao=" + bookDao + "]";
}
}
最后是BookDao
类
package com.atguigu.dao;
//名字默认是类名首字母小写
@Repository
public class BookDao {
private String lable = "1";
public String getLable() {
return lable;
}
public void setLable(String lable) {
this.lable = lable;
}
@Override
public String toString() {
return "BookDao [lable=" + lable + "]";
}
}
以上三个类没什么需要说的,无须关注类的具体内容,只须关注类上的注解,和类所处的包即可。
与上节同样的,我们采用Javaconfig类的方式,还是需要一个配置类。
所以我们新建:MainConfig
类,作为我们的配置类
package com.atguigu.config;
//配置类==配置文件
@Configuration //告诉Spring这是一个配置类
@ComponentScan(value="com.atguigu") // 注意这一行。
public class MainConfig {
//给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
@Bean(name = "person")
public Person person01(){
return new Person("lisi", 20);
}
}
在配置类上加了@ComponentScan注解,这里value="com.atguigu"
写成basePackages="com.atguigu"
都是指明我们需要扫描的包
我们写个测试方法:
public class IOCTest {
@SuppressWarnings("resource")
@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
}
}
加载配置类,并获取到容器中所有的Bean的名字,然后遍历进行打印
我们看下打印结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory // 这几个都是spring容器本身的
mainConfig
bookController
bookDao
bookService
person
我们可以看到将com.atguigu下所有的bean都已经扫描了进来,这里说一下MainConfig这个配置类,也在扫描的包下。它的类上有个注解@Configuration,表示配置类也是一个bean。还有个person是我们在@Bean注解定义的Bean.
接下来我们要对@ComponentScan注解进行详细的讲解。
1.我们有这样一样一个需求:不扫描@Controller注解。
该怎么写呢
@ComponentScan(basePackages="com.atguigu",excludeFilters= {@Filter(type=FilterType.ANNOTATION,classes={Controller.class})})
这就表示排除掉了@Controller注解,
看看打印结果:
// 可以看到确实没有bookController类了,它被@Controller注解所修饰,所以被排除在了扫描之外,自然也不没有纳入容器之中
mainConfig
bookDao
bookService
person
2.只扫描@Repository标注的注解
该如何写呢??
@ComponentScan(basePackages="com.atguigu",includeFilters= {@Filter(type=FilterType.ANNOTATION,
classes={Repository.class})},useDefaultFilters=false)
测试方法不变,打印结果:
mainConfig
bookDao
person
可以看到 容器中只有bookDao这一个bean了。
注意:useDefaultFilters=false是禁用掉默认的扫描规则,默认当然是扫描包下的@Controller、@Service、@Repository,@Component这四大金刚咯(其实还包括@Configuration注解),所以禁用掉,就不再扫描了,那么只扫描我们定义的。这点与上面的排除规则不同,注意理解,毕竟排除是从所有扫描中再排除。
让我们再深入一点,嘿嘿
我们来看看 @ComponentScan注解里面能写哪些东西
常用的几个注解我们已经讲解过了,
我们主要来看下excludeFilters和includeFilters的写法
在@ComponentScan中,我们拿到这个类的源码看看呗。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
boolean useDefaultFilters() default true;
Filter[] includeFilters() default {};
Filter[] excludeFilters() default {};
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
FilterType type() default FilterType.ANNOTATION; // 过滤的类型,默认是通过注解的类型,
@AliasFor("classes")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] classes() default {};
String[] pattern() default {};
}
}
我们发现它们是Filter数组类型,从我们刚刚的写法中也能略窥一二。这个Filter也是一个注解,刚好定义在内部,
也就是说
excludeFilters= {@Filter(type=FilterType.ANNOTATION,classes={Controller.class})}
的意思是说排除掉Controller类型的注解。
那除了通过注解的类型进行排除,还有其他的方式么?
那我们就要去上面这个FilterType.ANNOTATION
中的FilterType
中一探究竟了。
发现它有五个类型,那我们再举个通过ASSIGNABLE_TYPE
的例子
比如这样@Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}
这就是说通过指定类型,排除掉BookService.class
类型,即不扫描,这其实包括了它的子类,父类等。
其他还有一种CUSTOM
也就是自定义过滤规则。不再讲解。
再回来,我们看看@ComponentScan的源码,发现它被@Repeatable(ComponentScans.class)注解所修饰,这个注解代表中,我们可以在类上重复加这个注解,定义多个不同的扫描策略。
该睡觉了,又是一个深夜了,晚安!
二、Spring中的@ComponentScan自动扫描组件的更多相关文章
- Spring学习(十四)----- Spring Auto Scanning Components —— 自动扫描组件
一. Spring Auto Scanning Components —— 自动扫描组件 1. Declares Components Manually——手动配置componen ...
- 分布式数据存储 之 Redis(二) —— spring中的缓存抽象
分布式数据存储 之 Redis(二) -- spring中的缓存抽象 一.spring boot 中的 StringRedisTemplate 1.StringRedisTemplate Demo 第 ...
- 关于spring中<context:component-scan base-package="" />写法
1.通配符形式<context:component-scan base-package="com.*" /> 2.全路径 <context:component-s ...
- Spring Boot 自动扫描组件
使用@ComponentScan自动扫描组件 案例准备 1.创建一个配置类,在配置类上添加 @ComponentScan 注解.该注解默认会扫描该类所在的包下所有的配置类,相当于之前的 <con ...
- Spring中@Autowired、@Resource和@Inject注解的使用和区别
在使用Spring进行项目开发的时候,会大量使用到自动装配,那自动装配是什么呢?简单来说:Spring 利用依赖注入(DI)功能,完成SpringIOC容器中各个组件之间的依赖关系赋值管理. 下面介绍 ...
- spring框架应用系列二:component-scan自动扫描注册装配
component-scan自动扫描注册装配 本文系作者原创,转载请注明出处:http://www.cnblogs.com/further-further-further/p/7717331.html ...
- Spring学习笔记之 Spring IOC容器(二) 之注入参数值,自动组件扫描方式,控制Bean实例化方式,使用注解方式
本节主要内容: 1. 给MessageBean注入参数值 2. 测试Spring自动组件扫描方式 3. 如何控制ExampleBean实例化方式 4. 使用注解方式重构Jdb ...
- Spring自动扫描组件
通常情况下,声明所有的Bean类或组件的XML bean配置文件,这样Spring容器可以检测并注册Bean类或组件. 其实,Spring是能够自动扫描,检测和预定义的项目包并实例化bean,不再有繁 ...
- spring中注解注入 context:component-scan 的使用说明
通常情况下我们在创建spring项目的时候在xml配置文件中都会配置这个标签,配置完这个标签后,spring就会去自动扫描base-package对应的路径或者该路径的子包下面的java文件,如果扫描 ...
随机推荐
- Spark 缓存机制
Spark中的缓存机制:避免spark每次都重算RDD以及它的所有依赖,cache().persist(). checkpoint(). 1.cache():会被重复使用,但是不能太大的RDD,将其c ...
- idea中properties配置文件 注释显示中文乱码问题
- js解决大文件断点续传
最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...
- WinDbg常用命令系列---单步执行p*
p (Step) p命令执行单个指令或源代码行,并可选地显示所有寄存器和标志的结果值.当子例程调用或中断发生时,它们被视为单个步骤. 用户模式: [~Thread] p[r] [= StartAddr ...
- proc near/far
proc是定义子程序的伪指令,位置在子程序的开始处,它和endp分别表示子程序定义的开始和结束两者必须成对出现. far是该子程序的属性,决定调用程序和子程序是否在同一代码段如下:为子程序定义及说明, ...
- 文件搜索命令find
1.路径加文件名搜索(find): 查找的是etc目录下的以init为名字的文件. 加通配符后为模糊搜索,只要文件名中含有init即可. 查找etc目录下以init开头的七位文件名. 2.搜索时不区分 ...
- Phalcon框架的编译安装 内存不足的解决办法
对症解决 有两种解决方法,一种是提升ECS系统内存.但是却要真金白银跟阿里云去购买的.另一种,则是手动创建swap交换文件.下面来介绍第二种方法. 第一步:首先确定系统是否已经开启swap交换分区: ...
- 用户价值和RFM模型
什么是用户价值? 用户价值就是对公司来说有用的地方,比如有的公司看中用户的消费能力,有的公司则看中用户的忠诚度 .各公司的业务目的不同,用户价值的体现自然也不同.这里主要说一下适用于电商的RFM模型. ...
- JavaScript高级程序编程(三)
2017-06-24 更新 北京连续三天下雨啦 乘性操作符 1.ECMA中定义了三种操作符,乘法 除法 和求模 并与其他语言相应操作符相同,再计算之前如果不是数值,会先去调用number()方法转 ...
- 干货 | 10分钟带你掌握branch and price(分支定价)算法超详细原理解析
00 前言 相信大家对branch and price的神秘之处也非常好奇了.今天我们一起来揭秘该算法原理过程.不过,在此之前,请大家确保自己的branch and bound和column gene ...