目录
@ComponentScan && @ComponentScans
@ComponentScan
&& @ComponentScans
1. 源码
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.annotation.AliasFor;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
// 作用同basePackages属性,String[]数组类型,指定要扫描的包名。如果指定了要扫描的包名,则Spring会扫描指定的包及其子包下的所有类。
@AliasFor("basePackages")
String[] value() default {};
// 作用同value属性,String[]数组类型,指定要扫描的包名。如果指定了要扫描的包名,则Spring会扫描指定的包及其子包下的所有类。
@AliasFor("value")
String[] basePackages() default {};
// Class<?>[]数组类型,指定要扫描的类的Class对象
Class<?>[] basePackageClasses() default {};
// Class<? extends BeanNameGenerator>类型,指定扫描类时,向IOC注入Bean对象时的命名规则
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
// Class<? extends ScopeMetadataResolver>类型,扫描类时,用于处理并转换符合条件的Bean的作用范围
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
// ScopedProxyMode类型,指定生成Bean对象时的代理方式,默认的代理方法是DEFAULT,也就是不使用代理
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
// String类型,用于指定扫描的文件类型,默认是扫描指定包下的**/*.class
String resourcePattern() default "**/*.class";
// boolean类型,是否自动检测@Component @Repository @Service @Controller注解,默认是true
boolean useDefaultFilters() default true;
// Filter[]数组类型,自定义组件扫描过滤规则,符合过滤规则的类的Bean定义信息会被注册到IOC容器中。includeFilters表示只包含对应的规则,当使用includeFilters()来指定只包含哪些注解标注的类时,需要禁用默认的过滤规则,也就是需要将useDefaultFilters属性设置为false。
// 除了符合过滤规则的类外,Spring内置类的Bean定义信息注册到IOC容器时不受过滤规则限制
Filter[] includeFilters() default {};
// Filter[]数组类型,自定义组件扫描过滤规则,excludeFilters表示排除使用对应的规则,符合过滤规则的类的Bean定义信息不会被注册到IOC容器中
Filter[] excludeFilters() default {};
// boolean类型,从Spring4.1版本开始提供,表示Spring扫描组件时是否采用懒加载 ,默认false,表示不开启懒加载
boolean lazyInit() default false;
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Filter {
// FilterType类型,表示过滤规则的类型
// ANNOTATION:按照注解进行过滤
// ASSIGNABLE_TYPE:按照给定的类型进行过滤
// ASPECTJ:按照ASPECTJ表达式进行过滤
// REGEX:按照正则表达式进行过滤
// CUSTOM:按照自定义规则进行过滤,使用自定义过滤规则时,自定义的过滤器需要实现org.springframework.core.type.filter.TypeFilter接口
FilterType type() default FilterType.ANNOTATION;
// Class<?>[]数组类型,过滤符合规则的类,作用同classes属性
@AliasFor("classes")
Class<?>[] value() default {};
// Class<?>[]数组类型,过滤符合规则的类,作用同value属性
@AliasFor("value")
Class<?>[] classes() default {};
// 如果FilterType取值为ASPECTJ,则此属性表示ASPECTJ表达式。
String[] pattern() default {};
}
}
2. 场景
使用Spring的注解开发应用程序时,如果需要将标注了Spring注解的类注入到IOC容器中,就需要使用@ComponentScan注解来扫描指定包下的类。同时,在Spring4.3版本开始,提供了@ComponentScans注解,在@ComponentScans注解中,支持配置多个@ComponentScan注解来扫描不同的包,配置不同的过滤规则。
3. 补充
3.1 FilterType
FilterType
枚举类的值
- ANNOTATION:
- 用于根据注解来过滤。例如,可以使用
@Component
注解来过滤出所有的组件。
- 示例:
@ComponentScan(basePackages = "com.example", includeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyCustomAnnotation.class))
- ASSIGNABLE_TYPE:
- 用于根据类型(即类或接口)来过滤。可以用来选择实现某个特定接口或者继承自某个特定类的组件。
- 示例:
@ComponentScan(basePackages = "com.example", includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MyService.class))
- ASPECTJ:
- 用于 AspectJ 表达式模式匹配的类型过滤。AspectJ 是一种面向切面编程的框架,它的表达式可以用来匹配类名、方法名等。
- 示例:
@ComponentScan(basePackages = "com.example", includeFilters = @Filter(type = FilterType.ASPECTJ, pattern = "com.example.service..*Service+"))
- REGEX:
- 用于正则表达式匹配的类型过滤。可以使用正则表达式来匹配类名。
- 示例:
@ComponentScan(basePackages = "com.example", includeFilters = @Filter(type = FilterType.REGEX, pattern = "com\\.example\\.service\\..*Service"))
- CUSTOM:
- 用于自定义过滤器。允许用户实现自己的
TypeFilter
接口,从而定义更复杂的过滤逻辑。
- 示例:java深色版本
@ComponentScan(basePackages = "com.example", includeFilters = @Filter(type = FilterType.CUSTOM, classes = MyCustomTypeFilter.class))
@ComponentScan(basePackages = "com.example", includeFilters = @Filter(type = FilterType.CUSTOM, classes = MyCustomTypeFilter.class))
使用示例
基于注解的过滤
@ComponentScan(basePackages = "com.example", includeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyCustomAnnotation.class)) public class AppConfig { }
基于类型的过滤
@ComponentScan(basePackages = "com.example", includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MyService.class)) public class AppConfig { }
基于 AspectJ 表达式的过滤
@ComponentScan(basePackages = "com.example", includeFilters = @Filter(type = FilterType.ASPECTJ, pattern = "com.example.service..*Service+")) public class AppConfig { }
基于正则表达式的过滤
@ComponentScan(basePackages = "com.example", includeFilters = @Filter(type = FilterType.REGEX, pattern = "com\\.example\\.service\\..*Service")) public class AppConfig { }
自定义过滤器
public class MyCustomTypeFilter implements TypeFilter { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { // 实现自定义的过滤逻辑 return metadataReader.getClassMetadata().getClassName().endsWith("Service"); }
}
@ComponentScan(basePackages = "com.example", includeFilters = @Filter(type = FilterType.CUSTOM, classes = MyCustomTypeFilter.class)) public class AppConfig { }