spring常用注解-@ComponentScan

@ComponentScan用法

ComponentScan为组件扫描,就是根据定义的扫描对应路径,把符合扫描规则的类装配到Spring容器中

@ComponentScan参数说明

@ComponentScan
valeu:只当于扫描的包
excludeFilters: 指定扫描的时候按照某种规则排除那些组件
includeFilters: 指定扫描的时候只需要包含那些组件
FilterType 有五种类型(ANNOTATION:注解类型;ASSIGNABLE_TYPE:ANNOTATION:指定的类型;ASPECTJ:按照Aspectj的表达式,基本上不会用到;REGEX:按照正则表达式;CUSTOM:自定义规则)

实体类

@Component
public class Dog {
    public  Dog(){
        System.out.println("this is Dog");
    }
}
@Component
public class Fish {

    public  Fish(){
        System.out.println("this is fish");
    }
}

ComponentScan配置扫描类

@ComponentScan(value = "com.honey.badger.nacos.test.config.scan")
public class MainConfig {

    @Bean
    public Cat cat(){
        return  new Cat();
    }

}

测试类

public class ConfigurationTest {
    public static void main(String[] args) {
      ApplicationContext anno = new AnnotationConfigApplicationContext(MainConfig.class);

      String[] beanName = anno.getBeanDefinitionNames();
        for (String name : beanName) {
            System.out.println(">>>>>: "+name);
        }
    }

运行结果

>>>>>: 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
>>>>>: mainConfig
>>>>>: dog
>>>>>: fish
>>>>>: cat

在上面的基础上,我们还可以是用ComponentScan的excludeFilters和includeFilters

excludeFilters

添加dogService和fishService实体类

@Service
public class DogService {

    public DogService(){
        System.out.println("this is DogService");
    }
}
@Service
public class DogService {

    public DogService(){
        System.out.println("this is DogService");
    }
}
@Service
public class FishService {

    public FishService(){
        System.out.println("this is FishService");
    }
}

配置实体类

@ComponentScan(
        value = "com.honey.badger.nacos.test.config.scan",
         excludeFilters = {
                //过滤注解
                @Filter(type = FilterType.ANNOTATION,classes = {Service.class}),
                //过滤某个类
                @Filter(type = FilterType.ASSIGNABLE_TYPE,value = {com.honey.badger.nacos.test.config.scan.DogService.class})
        },
        useDefaultFilters = true
)
public class MainConfig {

    @Bean
    public Cat cat(){
        return  new Cat();
    }

}

测试类

public class ConfigurationTest {
    public static void main(String[] args) {
      ApplicationContext anno = new AnnotationConfigApplicationContext(MainConfig.class);

      String[] beanName = anno.getBeanDefinitionNames();
        for (String name : beanName) {
            System.out.println(">>>>>: "+name);
        }
    }

运行结果

>>>>>: 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
>>>>>: mainConfig
>>>>>: dog
>>>>>: fish
>>>>>: cat

这里我们看到dogService和fishService实体并没有加载到我们spring的容器中

includeFilters

@ComponentScan 的一个 useDefaultFilters 属性的用法,该属性默认值为 true,也就是说 spring 默认会自动发现被 @Component、@Repository、@Service 和 @Controller 标注的类,并注册进容器中。要达到只包含某些包的扫描效果,就必须将这个默认行为给禁用掉(在 @ComponentScan 中将 useDefaultFilters 设为 false 即可)

@ComponentScan(
        value = "com.honey.badger.nacos.test.config.scan",
        includeFilters = {
                //过滤注解
                @Filter(type = FilterType.ANNOTATION,classes = {Service.class}),
         },
        useDefaultFilters = false
)
@Configuration
public class MainConfig {

    @Bean
    public Cat cat(){
        return  new Cat();
    }

}

运行结果

>>>>>: 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
>>>>>: mainConfig
>>>>>: dogService
>>>>>: fishService
>>>>>: cat

这里面Dog和fish类就没有被扫描出来

@ComponentScans

在我们使用多个ComponentScan注解,我们可以使用@ComponentScans注解,从而实现多个扫描的规则,同样也需要加上@Configurtion注解,否则无效

@ComponentScans源码我们看出,他是用有多个ComponentScan组成的

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface ComponentScans {
    ComponentScan[] value();
}

配置类

@ComponentScans(value = {
    @ComponentScan( value = "com.honey.badger.nacos.test.config"),
    @ComponentScan( value = "com.honey.badger.nacos.test.controller")
    }
)
@Configuration
public class MainConfig {

    @Bean
    public Cat cat(){
        return  new Cat();
    }

}

运行结果

>>>>>: mainConfig
>>>>>: cat
>>>>>: dog
>>>>>: dogService
>>>>>: fish
>>>>>: fishService
>>>>>: scopedTarget.helloController
>>>>>: helloController

添加自定义过滤规则

在前面我使用@Filter注解的时候,type属性中FilterTypede的枚举类型:

public enum FilterType {

    //注解方式
    ANNOTATION,
    //指定类型 比如某个类
    ASSIGNABLE_TYPE,
    //表达式
    ASPECTJ,
    //正则
    REGEX,
    //自定义
    CUSTOM

}

那我先下面将实现一个的自定义的方式来加载实体类

自定义过滤

public class MyScanFilter implements TypeFilter {

    @Override
   public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {
         //获取当前扫描到的类的注解的元数据
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前的扫描的类的元数据
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 获取当前扫描到的类的资源信息
        Resource resource = metadataReader.getResource();

        if(classMetadata.getClassName().contains("Service")){
            System.out.println("className:"+classMetadata.getClassName());
            return  true;
        }

        return  false;
    }
}

配置类

@ComponentScan(
        value = "com.honey.badger.nacos.test.config",
        includeFilters = { @Filter(type = FilterType.CUSTOM,value = {MyScanFilter.class})},
        useDefaultFilters = false)
@Configuration
public class MainConfig {

}

运行结果

>>>>>: mainConfig
>>>>>: dogService
>>>>>: fishService

你可能感兴趣的:(spring常用注解-@ComponentScan)