@ComponentScan

Srping注解 @ComponentScan

1.创建一个配置类,在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类,相当于之前的
 <context:component-scan>
2.使用 ApplicationContext 的 getBeanDefinitionNames() 方法和getBeanDefinitionCount()获取已经注册到容器中的 bean 的名称以及数量
@SpringBootApplication
public class ZzyNotesApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ZzyNotesApplication.class, args);
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanName : beanDefinitionNames) {
            System.out.println("beanName: " + beanName);
        }
        System.out.println("bean总数:"+context.getBeanDefinitionCount());
    }
}
3.@ComponentScan
@SpringBootApplication注解中已经存在,也可以根据需要自定义		
@SpringBootApplication(scanBasePackages = "")
常用参数:
  1.value || basePackages = "包路径,默认当前类所在包"
  2.excludeFilters 使用 excludeFilters 来按照规则排除某些包的扫描。
  3.includeFilters 用includeFilters配置 扫描的类 ,
               !优先级由上之下,比如自定义的MyTypeFilter如果已经Bean已经在ioc容器中,或者上面的excludeFilters已经过滤掉这个Bean,则不扫描这个类
               参数:
               FilterType.ANNOTATION :注解名规则,Service.class
               FilterType.ASSIGNABLE_TYPE : 按照给定的类型,比如当前类型的父子类。
               FilterType.ASPECTJ :使用aspectj表达式
               FilterType.REGEX :使用正则指定
               FilterType.CUSTOM4.useDefaultFilters 默认为true ,会优先执行默认的过滤器 对 @Component、@ManagedBean、@Named注解的Bean进行扫描 所以要改为false
配置类代码如下
@Configuration
@ComponentScans(
        {
        @ComponentScan(value = "com.zzy.zzyNotes" ,useDefaultFilters = false),
        @ComponentScan(value = "com.zzy.zzyNotes.spring.createBean",
                excludeFilters = {
                        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Service.class}),//排除包含注解Service的类(不生效,原因未知)
                        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {ExcludeMyAnnotation.class})//排除包含注解MyAnnotation2的类
                },
                includeFilters = {
                        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {IncludeMyAnnotation.class}),//指定扫描包换注解MyAnnotation的类
                        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),//指定注解扫描包换注解Controller的类
                        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE , classes = {Person2.class}),//指定类型Person2的类
                        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})//自定义过滤规则
                }
                , useDefaultFilters = false//这个没有效果,必须在启动类上的@ComponentScan( useDefaultFilters = false)中配置 false
        )
        }
)
public class BeanConfig {
}
/**
 * @author zzy
 * @createDate: 2021-12-30 16:26:50
 * @description: 自定义注解 指定某个类被扫描
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IncludeMyAnnotation {
}

/**
 * @author zzy
 * @createDate: 2021-12-30 16:26:50
 * @description: 自定义注解 排除某个类被扫描
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcludeMyAnnotation {
}

/**
 * 扫描包自定义规则
 * metadataReader:读取到当前正在扫描类的信息
 * metadataReaderFactory:可以获取到其他任何类的信息
 *	注意:只有不满足其它的规则,才会被自定义过滤规则判断
 * @author zzy
 */
public class MyTypeFilter implements TypeFilter {

    /**
    * @description:  扫描规则
    * @params:
    * @return: 返回true 加入IOC容器 false ,排除
    */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
        throws IOException {
        //获取当前类注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前正在扫描类的信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前类资源信息 (比如类存在哪个盘,类的路径  )
        Resource resource = metadataReader.getResource();
        String name = classMetadata.getClassName();
        System.out.println("Filter扫描的类名:" + name);
        if(name.contains("Person3")){
            return true;
        }
        return false;
    }
}
/**
 * @author zzy
 * @createDate: 2021-12-30 10:08:35
 * @description: 创建Bean Person1 加IncludeMyAnnotation
 */
@IncludeMyAnnotation
public class Person1 {
}
/**
 * @author zzy
 * @createDate: 2021-12-30 10:10:37
 * @description: 创建Bean Person1 加@ExcludeMyAnnotation 被排除
 * 正常有@Component就会被扫描,加了@ExcludeMyAnnotation就会被排除
 */
@ExcludeMyAnnotation
@Component
public class Person2 {
}
/**
 * @author zzy
 * @createDate: 2021-12-30 17:03:44
 * @description: 创建Bean Person3  符合MyTypeFilter过滤规则
 */
public class Person3 {
}
优先级

自定义的@ComponentScan优先级大于@SpringBootApplication默认的,要注意的是,
自定义的@ComponentScan的路径一定要包含启动类项目路径,默认为配置类所在的路径

注意

1.自定义@ComponentScan时注意控制的路径范围
2.有重名的Bean会注册失败

问题!!!

1.spring 有默认的规律规则 会对 @Component、@ManagedBean、@Named注解的Bean进行扫描,如果设置了 
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Service.class})
但是加了@service的类依然被注册到ioc
所以要设置 useDefaultFilters = false 
但是!!!
我这样设置,加了@Service的类还是被注册到Ioc,原因找了半天没找到,希望有了解的人可以解答疑问,谢谢
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值