zoukankan      html  css  js  c++  java
  • 一、Spring注解之@ComponentScan

    Spring注解之@ComponentScan

    【1】@ComponentScan注解是什么

    @ComponentScan主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中

    【2】@ComponentScan注解的详细使用

    1、创建一个配置类,在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的类

    package com.zl.springbase.config;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan
    public class MyConfig {
    }
    

    我的类结构如下:类MyDao上面添加了@Repository注解

    测试程序:

    public class TestComponentScan {
        @Test
        public void test1(){
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            String[] names = context.getBeanDefinitionNames();
            for (String name : names) {
                System.out.println("beanName"+name);
            }
        }
    }
    /**
    beanName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    beanName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    beanName: org.springframework.context.annotation.internalCommonAnnotationProcessor
    beanName: org.springframework.context.event.internalEventListenerProcessor
    beanName: org.springframework.context.event.internalEventListenerFactory
    beanName: myConfig
    beanName: myDao
    */
    

    2、指定要扫描的包(使用@ComponentScan 的 valule 属性来配置),创建一个controller 包,并在该包下新建一个 MyController 类并添加@Controller注解。

    @Configuration
    @ComponentScan(value = {"com.zl.springBase.controller"})
    public class MyConfig {
    }
    
    /**测试结果
    beanName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    beanName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    beanName: org.springframework.context.annotation.internalCommonAnnotationProcessor
    beanName: org.springframework.context.event.internalEventListenerProcessor
    beanName: org.springframework.context.event.internalEventListenerFactory
    beanName: myConfig
    beanName: myController
    */
    

    3、excludeFilters 和 includeFilters 的使用

    • excludeFilters

    ①使用 excludeFilters 来按照注解类型排除某些包的扫描

    @Configuration
    @ComponentScan(value = {"com.zl.springBase"},excludeFilters = {
            @Filter(type = FilterType.ANNOTATION,value = {Controller.class})
    })
    public class MyConfig {
    }
    
    /**测试结果
    beanName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    beanName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    beanName: org.springframework.context.annotation.internalCommonAnnotationProcessor
    beanName: org.springframework.context.event.internalEventListenerProcessor
    beanName: org.springframework.context.event.internalEventListenerFactory
    beanName: myConfig
    beanName: myDao
    */
    

    ​ excludeFilters 的参数是一个 Filter[] 数组,然后指定 FilterType 的类型为 ANNOTATION,也就是通过注解来过滤,最后的 value 则是Controller 注解类。配置之后,在 spring 扫描的时候,就会跳过 com.zl.springBase包下,所有被 @Controller 注解标注的类。

    ②使用 excludeFilters 来按照指定类型排除某些包的扫描

    @Configuration
    @ComponentScan(value = {"com.zl.springBase"},excludeFilters = {
            @Filter(type = FilterType.ASSIGNABLE_TYPE,value = {MyDao.class})
    })
    public class MyConfig {
    }
    
    /**测试结果
    beanName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    beanName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    beanName: org.springframework.context.annotation.internalCommonAnnotationProcessor
    beanName: org.springframework.context.event.internalEventListenerProcessor
    beanName: org.springframework.context.event.internalEventListenerFactory
    beanName: myConfig
    beanName: myController
    */
    

    FilterType 的类型为 ASSIGNABLE_TYPE,就是通过指定类型来过滤,value指定为MyDao,则会过滤掉MyDao这个类。

    ③使用 excludeFilters 来按照自定义类型排除某些包的扫描

    首先创建一个实现 TypeFilter 接口的 CustomTypeFilter 类,并实现其 match 方法。

    这里简单对扫描到的类名进行判断,如果类名包含”Co“的就符合条件,也就会注入到容器中。

    public class CustomTypeFilter implements TypeFilter {
        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("Co")) {
                return true;
            }
            return false;
        }
    }
    

    MyConfig:

    @Configuration
    @ComponentScan(value = {"com.zl.springBase"},excludeFilters = {
            @Filter(type = FilterType.CUSTOM,value = {CustomTypeFilter.class})
    })
    public class MyConfig {
    }
    
    /**测试结果
    beanName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    beanName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    beanName: org.springframework.context.annotation.internalCommonAnnotationProcessor
    beanName: org.springframework.context.event.internalEventListenerProcessor
    beanName: org.springframework.context.event.internalEventListenerFactory
    beanName: myConfig
    beanName: myDao
    */
    

    可以看到MyController已经被过滤掉了,myCofig之所以没有被过滤掉是因为它本身是一个配置类,@Configuration注解类里面包含了@Component注解,所以IOC容器启动后MyConfig会被自动加入容器当中。

    • includeFilters

    使用 includeFilters 来按照规则只包含某些包的扫描

    在创建一个 service 的包,并创建一个 MyService 类,再加上一个 @Service 注解

    修改MyConfig类:

    @Configuration
    @ComponentScan(value = {"com.zl.springBase"},includeFilters = {
            @Filter(type = FilterType.ANNOTATION,value = {Controller.class})
    })
    public class MyConfig {
    }
    
    /**测试结果
    beanName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    beanName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    beanName: org.springframework.context.annotation.internalCommonAnnotationProcessor
    beanName: org.springframework.context.event.internalEventListenerProcessor
    beanName: org.springframework.context.event.internalEventListenerFactory
    beanName: myConfig
    beanName: myDao
    beanName: myController
    beanName: myService
    */
    

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

  • 相关阅读:
    02SpringMvc_springmvc快速入门小案例(XML版本)
    01SpringMvc_初识工作流程
    07JavaIO详解_字符流
    06JavaIO详解_IO流中的设计模式-装饰者模式
    05JavaIO详解_仿照IO源码自己去实现一个IO流(为了加深印象,本身没有价值)
    作为程序员,我到底在恐慌什么
    android:layout_weight详解
    Android 遍历界面控件
    一个Activity中使用两个layout实例
    Android获取文件的MD5值
  • 原文地址:https://www.cnblogs.com/lee0527/p/11734122.html
Copyright © 2011-2022 走看看