文章目录
- 1. 作用
- 2. @ComponentScan源码
- 3. SpringBootApplicatioscan中的scanBasePackages属性
- 4. 注意事项
- 4.1 Spring Boot项目
- 4.2 非 Spring Boot项目
1. 作用
创建一个配置类,在配置类JavaConfig形式上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类,相当于之前的 <context:component-scan>
参见 《JavaConfig、@Configuration、@ComponentScan入门例子》
2. @ComponentScan源码
@ComponentScan 的作用就是根据定义的扫描路径,把符合扫描规则的类装配到spring容器中,注解定义如下:
package org.springframework.context.annotation;
@Retention(RetentionPolicy.RUNTIME)
//表示只可以声明在类上
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value") //表示和value等价
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
-
@Target({}) 表示只可以声明在类上
-
value 表示用法如
@ComponentScan(value="")
也可以简写为@ComponentScan("")
,省略value=
-
basePackages,表示用法如
@ComponentScan(basePackages="")
,由于和value等价(@AliasFor("value")
),也可简写为@ComponentScan("")
-
nameGenerator: bean的名称的生成器
-
useDefaultFilters: 是否开启对@Component,@Repository,@Service,@Controller的类进行检测
-
includeFilters: 包含的过滤条件
-
:按照注解过滤
-
FilterType.ASSIGNABLE_TYPE:按照给定的类型
-
:使用ASPECTJ表达式
-
:正则
-
:自定义规则
-
-
excludeFilters: 排除的过滤条件,用法和includeFilters一样
一个稍完整的示例:
// 和 下的类都不会被扫描
@ComponentScan(basePackages = {""},
excludeFilters = {@(type = FilterType.REGEX,
pattern = "\\..*"),
@(type = FilterType.REGEX, pattern = "\\..*")})
3. SpringBootApplicatioscan中的scanBasePackages属性
本质上,SpringBootApplicatioscan中的scanBasePackages属性底层原理正是复用了@ComponentScan,因此语法和意义基本一致
...
public @interface SpringBootApplication {
//复用了@ComponentScan
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
@AliasFor标签表示别名的意义,可以理解为等价于
因此,下面2种用法相同:
@SpringBootApplication (scanBasePackages="")
public class MyClass {
package com.test;
@ComponentScan("")
@SpringBootApplication
public class MyClass {
4. 注意事项
4.1 Spring Boot项目
当使用Spring Boot项目时,可以不指定加载路径,即不使用@ComponentScan
或@SpringBootApplication (scanBasePackages=""
),默认会加载MyClass所在的包
举个例子,看下面定义的类:
package com.test;
@SpringBootApplication
public class MyClass {
MyClass 的package为,这个类使用了@SpringBootApplication注解,该注解定义了Spring将自动扫描包及其子包下的bean。
如果你项目中所有的类都定义在包及其子包下,那你不需要做任何事。
但假如你一个类定义在包com.test2下,则你需要将这个新包也纳入扫描的范围,有两个方案可以达到这个目的:
-
方案1, 定义@CoponentScan(“com”)
这么做扫描的范围扩大到整个父包com
-
方案2, 定义分别扫描两个包
@ComponentScan({“”,”com.test2”})
4.2 非 Spring Boot项目
在非Spring Boot项目中,我们必须显式地使用@ComponentScan
注解定义被扫描的包,可以通过XML文件在应用上下文中定义或在Java代码中对应用上下文定义,否则会加载不到预期的bean。
参考:
《@ComponentScan 详解》 列出了具体参数的用法
《Spring注解——使用@ComponentScan自动扫描组件》 包含讲解和例子
《Spring和SpringBoot中的@Component 和@ComponentScan注解用法介绍和注意事项》