@ComponentScan 详解

@ComponentScan 的作用就是根据定义的扫描路径,把符合扫描规则的类装配到spring容器中,注解定义如下。

 
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    @AliasFor("basePackages")
    String[] value() default {};
 
    @AliasFor("value")
    String[] basePackages() default {};
 
    Class<?>[] basePackageClasses() default {};
 
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
 
    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
 
    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
 
    String resourcePattern() default "**/*.class";
    boolean useDefaultFilters() default true;
    ComponentScan.Filter[] includeFilters() default {};
    ComponentScan.Filter[] excludeFilters() default {};
    boolean lazyInit() default false;
    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;
        @AliasFor("classes")
        Class<?>[] value() default {};
        @AliasFor("value")
        Class<?>[] classes() default {};
        String[] pattern() default {};
    }
}

basePackages与value:  用于指定包的路径,进行扫描

basePackageClasses: 用于指定某个类的包的路径进行扫描

nameGenerator: bean的名称的生成器

useDefaultFilters: 是否开启对@Component,@Repository,@Service,@Controller的类进行检测

includeFilters: 包含的过滤条件

            FilterType.ANNOTATION:按照注解过滤

            FilterType.ASSIGNABLE_TYPE:按照给定的类型

            FilterType.ASPECTJ:使用ASPECTJ表达式

            FilterType.REGEX:正则

            FilterType.CUSTOM:自定义规则

excludeFilters: 排除的过滤条件,用法和includeFilters一样

 

我的工程结构如下,测试对controller和service的扫描,其中HelloController没有加@Controller等任何注解,就是一个普通类。

修改配置类如下:应用默认的过滤器,扫描service包:

 
  1. @Configuration

  2. @ComponentScan(value = "com.xhx.spring.service",

  3. useDefaultFilters = true

  4. )

  5. public class MyConfig {

  6. }

系统注入了两个service进去

 

改成如下所示:HelloController所在的包的类也被扫描了进去

 
  1. @Configuration

  2. @ComponentScan(value = "com.xhx.spring.service",

  3. useDefaultFilters = true,

  4. basePackageClasses = HelloController.class

  5. )

  6. public class MyConfig {

  7. }

系统中会注入下面就给类

把默认的过滤器关掉,扫描带Controller注解的。

 
  1. @Configuration

  2. @ComponentScan(value = "com.xhx.spring",

  3. useDefaultFilters = false,

  4. includeFilters = {

  5. @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})

  6. }

  7. )

  8. public class MyConfig {

  9. }

 

按照类的类型扫描,虽然HelloController没有加注解,但是被注入到了spring容器中

 
  1. @Configuration

  2. @ComponentScan(value = "com.xhx.spring",

  3. useDefaultFilters = false,

  4. includeFilters = {

  5. @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {HelloController.class})

  6. }

  7. )

  8. public class MyConfig {

  9. }

自定义扫描过滤器

package com.xhx.spring.componentscan.config;
 
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
 
import java.io.IOException;
 
/**
 * xuhaixing
 * 2018/9/18 23:07
 **/
public class MyTypeFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        String className = metadataReader.getClassMetadata().getClassName();
        if(className.contains("Controller")){
            return true;
        }
        return false;
    }
}

修改配置类

@Configuration
@ComponentScan(value = "com.xhx.spring",
        useDefaultFilters = false,
        includeFilters = {
            @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
        }
)
public class MyConfig {
}

输出结果:

 

输出spring容器中的bean的测试类:只过滤输出了名字中含有hello的类。

package com.xhx.spring.componentscan;
 
import com.xhx.spring.componentscan.config.MyConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
 
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
 
@RunWith(SpringRunner.class)
@SpringBootTest
public class ComponentScanApplicationTests {
 
    @Test
    public void testLoads() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        List<String> hello = Arrays.stream(context.getBeanDefinitionNames()).collect(Collectors.toList());
        hello.stream().filter(name->name.contains("hello")).peek(System.out::println).count();
    }
 
}

 

  • 22
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值