* @ComponentScan(
basePackageClasses
= {BookDao.class, BookService.class})
Class<?>
[]
basePackageClasses() default {}
* 命名注册的Bean,可以自定义实现命名Bean,
* 1、@ComponentScan(
value
=
"spring.annotation.componentscan"
,nameGenerator = MyBeanNameGenerator.class)
* MyBeanNameGenerator.class 需要实现 BeanNameGenerator 接口,所有实现BeanNameGenerator 接口的实现类都会被调用
* 2、使用 AnnotationConfigApplicationContext 的 setBeanNameGenerator方法注入一个BeanNameGenerator
* BeanNameGenerator
beanNameGenerator
= (definition,registry)-> String.valueOf(new Random().nextInt(
1000
))
* AnnotationConfigApplicationContext
annotationConfigApplicationContext
= new AnnotationConfigApplicationContext()
* annotationConfigApplicationContext.setBeanNameGenerator(beanNameGenerator)
* annotationConfigApplicationContext.register(MainConfig2.class)
* annotationConfigApplicationContext.refresh()
* 第一种方式只会重命名@ComponentScan扫描到的注解类
* 第二种只有是初始化的注解类就会被重命名
* 列如第一种方式不会重命名 @Configuration 注解的bean名称,而第二种就会重命名 @Configuration 注解的Bean名称
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class
* 用于解析@Scope注解,可通过 AnnotationConfigApplicationContext 的 setScopeMetadataResolver 方法重新设定处理类
* ScopeMetadataResolver
scopeMetadataResolver
= definition -> new ScopeMetadata()
* AnnotationConfigApplicationContext
annotationConfigApplicationContext
= new AnnotationConfigApplicationContext()
* annotationConfigApplicationContext.setScopeMetadataResolver(scopeMetadataResolver)
* annotationConfigApplicationContext.register(MainConfig2.class)
* annotationConfigApplicationContext.refresh()
* 也可以通过@ComponentScan 的 scopeResolver 属性设置
*@ComponentScan(
value
=
"spring.annotation.componentscan"
,scopeResolver = MyAnnotationScopeMetadataResolver.class)
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class
* 用来设置类的代理模式
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT
* 扫描路径 如
resourcePattern
=
"**/*.class"
* 使用 includeFilters 和 excludeFilters 会更灵活
String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN
* 指示是否应启用对带有{@code @Component},{@ code @Repository},
* {@ code @Service}或{@code @Controller}注释的类的自动检测。
boolean useDefaultFilters() default true
* 对被扫描的包或类进行过滤,若符合条件,不论组件上是否有注解,Bean对象都将被创建
* @ComponentScan(
value
=
"spring.annotation.componentscan"
,includeFilters = {
* @ComponentScan.Filter(
type
= FilterType.ANNOTATION, classes = {Controller.class, Service.class}),
* @ComponentScan.Filter(
type
= FilterType.ASSIGNABLE_TYPE, classes = {SchoolDao.class}),
* @ComponentScan.Filter(
type
= FilterType.CUSTOM, classes = {MyTypeFilter.class}),
* @ComponentScan.Filter(
type
= FilterType.ASPECTJ, pattern =
"spring.annotation..*"
),
* @ComponentScan.Filter(
type
= FilterType.REGEX, pattern =
"^[A-Za-z.]+Dao$"
)
* },
useDefaultFilters
=
false
)
* useDefaultFilters 必须设为 false
Filter
[]
includeFilters() default {}
* 指定哪些类型不适合进行组件扫描。
* 用法同 includeFilters 一样
Filter
[]
excludeFilters() default {}
* 指定是否应注册扫描的Bean以进行延迟初始化。
* @ComponentScan(
value
=
"spring.annotation.componentscan"
,lazyInit =
true
)
boolean lazyInit() default false
* 用于 includeFilters 或 excludeFilters 的类型筛选器
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
* 要使用的过滤器类型,默认为 ANNOTATION 注解类型
* @ComponentScan.Filter(
type
= FilterType.ANNOTATION, classes = {Controller.class, Service.class})
FilterType type() default FilterType.ANNOTATION
* 过滤器的参数,参数必须为class数组,单个参数可以不加大括号
* 只能用于 ANNOTATION 、ASSIGNABLE_TYPE 、CUSTOM 这三个类型
* @ComponentScan.Filter(
type
= FilterType.ANNOTATION, value = {Controller.class, Service.class})
* @ComponentScan.Filter(
type
= FilterType.ASSIGNABLE_TYPE, classes = {SchoolDao.class})
* @ComponentScan.Filter(
type
= FilterType.CUSTOM, classes = {MyTypeFilter.class})
@AliasFor("classes")
Class<?>
[]
value() default {}
* 作用同上面的 value 相同
* ANNOTATION 参数为注解类,如 Controller.class, Service.class, Repository.class
* ASSIGNABLE_TYPE 参数为类,如 SchoolDao.class
* CUSTOM 参数为实现 TypeFilter 接口的类 ,如 MyTypeFilter.class
* MyTypeFilter 同时还能实现 EnvironmentAware,BeanFactoryAware,BeanClassLoaderAware,ResourceLoaderAware
* 这四个接口
* EnvironmentAware
* 此方法用来接收 Environment 数据 ,主要为程序的运行环境,Environment 接口继承自 PropertyResolver 接口,
* 详细内容在下方
* @Override
* public void setEnvironment(Environment environment) {
* String
property
= environment.getProperty(
"os.name"
)
* BeanFactoryAware
* BeanFactory Bean容器的根接口,用于操作容器,如获取bean的别名、类型、实例、是否单例的数据
* @Override
* public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
* Object
bean
= beanFactory.getBean(
"BeanName"
)
* BeanClassLoaderAware
* ClassLoader 是类加载器,在此方法里只能获取资源和设置加载器状态
* @Override
* public void setBeanClassLoader(ClassLoader classLoader) {
* ClassLoader
parent
= classLoader.getParent()
* ResourceLoaderAware
* ResourceLoader 用于获取类加载器和根据路径获取资源
* public void setResourceLoader(ResourceLoader resourceLoader) {
* ClassLoader
classLoader
= resourceLoader.getClassLoader()
@AliasFor("value")
Class<?>
[]
classes() default {}
* 这个参数是 classes 或 value 的替代参数,主要用于 ASPECTJ 类型和 REGEX 类型
* ASPECTJ 为 ASPECTJ 表达式
* @ComponentScan.Filter(
type
= FilterType.ASPECTJ, pattern =
"spring.annotation..*"
)
* REGEX 参数为 正则表达式
* @ComponentScan.Filter(
type
= FilterType.REGEX, pattern =
"^[A-Za-z.]+Dao$"
)
String
[]
pattern() default {}
1.环境准备
创建Maven项目,添加依赖:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.26.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
创建bean,controller,dao,service层,并在类上加上对应的注解,项目结构如下:
编写测试类,如下:
public class IoCTest {
@Test
public void test01() {
ApplicationContext applicationContext=new AnnotationConfigApplicationContext(SpringConfig.class);
String[] names= applicationContext.getBeanDefinitionNames();
for(String i:names) {
System.out.println(i);
2.excludeFilters的使用
使用excludeFilters不扫描com.learn包中的Controller、Service注解,如下:
@Configuration
@ComponentScan(basePackages = "com.learn",excludeFilters = {
@Filter(type = FilterType.ANNOTATION,classes = {Controller.class,Service.class})
public class SpringConfig {
上面使用的excludeFilters用于设置排除的过滤条件,实现Filter接口的type属性用于设置过滤类型,默认值为FilterType.ANNOTATION,提供了这几个过滤类型:
FilterType.ANNOTATION:按照注解过滤
FilterType.ASSIGNABLE_TYPE:按照给定的类型过滤
FilterType.ASPECTJ:按照ASPECTJ表达式过滤
FilterType.REGEX:按照正则表达式过滤
FilterType.CUSTOM:按照自定义规则过滤
classes和value属性为过滤器的参数,必须为class数组,类只能为以下三种类型:
ANNOTATION 参数为注解类,如 Controller.class, Service.class,
Repository.class
ASSIGNABLE_TYPE 参数为类,如 SchoolDao.class
CUSTOM 参数为实现 TypeFilter 接口的类 ,如 MyTypeFilter.class
3.includeFilters的使用
includeFilters属性用于定义扫描过滤条件,满足该条件才进行扫描。用法与excludeFilters一样。
但是因为useDefaultFilters属性默认为true,即使用默认的过滤器,启用对带有@Component,@Repository,@Service,@Controller注释的类的自动检测。会将带有这些注解的类注册为bean装配到IoC容器中。所以使用includeFilters时,需要把useDefaultFilters设置为false,如下:
@Configuration
@ComponentScan(basePackages = "com.learn",includeFilters = {
@Filter(type = FilterType.ANNOTATION,classes = {Controller.class,Service.class})
},useDefaultFilters = false)
public class SpringConfig {
结果如下,只扫描了带有Controller,Service注解的自定义的类:
4.自定义过滤规则
@ComponentScan注解扫描或解析的bean只能是Spring内部所定义的,比如@Component、@Service、@Controller或@Repository。如果要扫描一些自定义的注解,就可以自定义过滤规则来完成这个操作。
自定义一个类MyTypeFilter实现TypeFilter接口,这样这个TypeFilter就扫描所有类并只通过类名包含了controller的类,如下:
public class MyTypeFilter implements TypeFilter {
* 两个参数的含义:
* metadataReader:包含读取到的当前正在扫描的类的信息
* metadataReaderFactory:可以获取到当前正在扫描的类的其他类信息(如父类和接口)
* match方法返回false即不通过过滤规则,true通过过滤规则
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
ClassMetadata classMetadata = metadataReader.getClassMetadata();
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
if(className.contains("controller")){
return true;
return false;
在@ComponentScan注解中进行配置,如下:
@Configuration
@ComponentScan(basePackages = "com.learn",includeFilters = {
@Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {Person.class}),
@Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class}),
},useDefaultFilters = false)
public class SpringConfig {
经过上面的配置,第一个@Filter通过FilterType.ASSIGNABLE_TYPE规定了只扫描Person类型的类,第二个@Filter通过FilterType.CUSTOM自定义过滤规则规定了只扫描类名包含controller的类。结果:
程序员麦冬
公众号:Java程序员聚集地
粉丝