在以往采用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)注解所修饰,这个注解代表中,我们可以在类上重复加这个注解,定义多个不同的扫描策略。


该睡觉了,又是一个深夜了,晚安!

最新文章

  1. Centos6下安装Mono和Jexus部署ASP.NET应用程序(纯干货)
  2. 【WP 8.1开发】一键锁屏
  3. mvcAPI (入门 1)
  4. 【转】C#中判断扫描枪输入与键盘输入
  5. JAVA如何将PDF转换SWF格式的FLASH
  6. 读取proc信息的可扩展实现
  7. XPath总结(转)
  8. haproxy redirect prefix
  9. C# 网络编程 Part.1
  10. boost在windows下的编译(vs2010)
  11. 电商指尖---(9).net发展Solr中间Facet特征
  12. Android jni 编程1(对基本类型字符串的操作)
  13. badboy录制兼容性有趣测试
  14. etcd raft如何实现成员变更
  15. 《阿里巴巴Android编码规范》阅读纪要(二)
  16. vue学习之路一:安装vue-element-admin项目
  17. Guava Cache源码详解
  18. Android播放图片动画
  19. Liferay7 BPM门户开发之19: 理解Service Builder体系
  20. 作用域&amp;作用域链和with,catch语句&amp;闭包

热门文章

  1. oracle取随机数,取固定行数的数
  2. 浏览器 cookie
  3. Java线程池(ExecutorService)使用
  4. sass环境搭建之node-sass,ruby
  5. C++中的常量指针和指针常量
  6. RESTful API Design: 13 Best Practices to Make Your Users Happy
  7. Python 04 Geany的安装和配置
  8. AGC028 E - High Elements
  9. 【BZOJ4475】 [Jsoi2015]子集选取
  10. GIT 安装和升级