Spring注解之 @ComponentScan 的详细介绍

作者: Arvin Chen 分类: Java 来源: Break易站(www.breakyizhan.com)
  •   Spring注解大全

    1,@ComponentScan注解是什么

    其实很简单,@ComponentScan主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中。我们在Spring注解之 @Configuration 的详细介绍 - Break易站 这篇文章中也有用到@ComponentScan。

    2,@ComponentScan注解的详细使用

    做过web开发的同学一定都有用过@Controller,@Service,@Repository注解,查看其源码你会发现,他们中有一个共同的注解@Component,没错@ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中,好下面咱们就先来简单演示一下这个例子

    在包com.breakyizhan.controller下新建一个UserController带@Controller注解如下:

    package com.breakyizhan.controller;
    import org.springframework.stereotype.Controller;
    @Controller
    public class UserController {
    }

    在包com.breakyizhan.service下新建一个UserService带@Service注解如下:

    package com.breakyizhan.service;
    import org.springframework.stereotype.Service;
    @Service
    public class UserService {
    }

    在包com.breakyizhan.dao下新建一个UserDao带@Repository注解如下:

    package com.breakyizhan.dao;
    import org.springframework.stereotype.Repository;
    @Repository
    public class UserDao {
    }

    新建一个配置类如下:

    /**
     * 主配置类  包扫描com.breakyizhan
     *
     * @date 2018年5月12日
     */
    @ComponentScan(value="com.breakyizhan")
    @Configuration
    public class MainScanConfig {
    }

    新建测试方法如下:

    AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainScanConfig.class);
            String[] definitionNames = applicationContext2.getBeanDefinitionNames();
            for (String name : definitionNames) {
                System.out.println(name);
    }

    运行结果如下:

    mainScanConfig
    userController
    userDao
    userService

    怎么样,包扫描的方式比以前介绍的通过@Bean注解的方式是不是方便很多,这也就是为什么web开发的同学经常使用此方式的原因了

    上面只是简单的介绍了@ComponentScan注解检测包含指定注解的自动装配,接下来让我们来看看@ComponentScan注解的更加详细的配置,在演示详细的配置之前,让我们先看看@ComponentScan的源代码如下:

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    @Repeatable(ComponentScans.class)
    public @interface ComponentScan {
        /**
         * 对应的包扫描路径 可以是单个路径,也可以是扫描的路径数组
         * @return
         */
        @AliasFor("basePackages")
        String[] value() default {};
        /**
         * 和value一样是对应的包扫描路径 可以是单个路径,也可以是扫描的路径数组
         * @return
         */
        @AliasFor("value")
        String[] basePackages() default {};
        /**
         * 指定具体的扫描的类
         * @return
         */
        Class<?>[] basePackageClasses() default {};
        /**
         * 对应的bean名称的生成器 默认的是BeanNameGenerator
         * @return
         */
        Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
        /**
         * 处理检测到的bean的scope范围
         */
        Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
        /**
         * 是否为检测到的组件生成代理
         * Indicates whether proxies should be generated for detected components, which may be
         * necessary when using scopes in a proxy-style fashion.
         * <p>The default is defer to the default behavior of the component scanner used to
         * execute the actual scan.
         * <p>Note that setting this attribute overrides any value set for {@link #scopeResolver}.
         * @see ClassPathBeanDefinitionScanner#setScopedProxyMode(ScopedProxyMode)
         */
        ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
        /**
         * 控制符合组件检测条件的类文件   默认是包扫描下的  **/*.class
         * @return
         */
        String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
        /**
         * 是否对带有@Component @Repository @Service @Controller注解的类开启检测,默认是开启的
         * @return
         */
        boolean useDefaultFilters() default true;
        /**
         * 指定某些定义Filter满足条件的组件 FilterType有5种类型如:
         *                                  ANNOTATION, 注解类型 默认
                                            ASSIGNABLE_TYPE,指定固定类
                                            ASPECTJ, ASPECTJ类型
                                            REGEX,正则表达式
                                            CUSTOM,自定义类型
         * @return
         */
        Filter[] includeFilters() default {};
        /**
         * 排除某些过来器扫描到的类
         * @return
         */
        Filter[] excludeFilters() default {};
        /**
         * 扫描到的类是都开启懒加载 ,默认是不开启的
         * @return
         */
        boolean lazyInit() default false;
    }

    a,演示basePackageClasses参数,如我们把配置文件改成如下:

    @ComponentScan(value="com.breakyizhan.dao",useDefaultFilters=true,basePackageClasses=UserService.class)
    @Configuration
    public class MainScanConfig {
    }

    测试结果如下:

    mainScanConfig
    userDao
    userService

    只有userDao外加basePackageClasses指定的userService加入到了spring容器中

    b,演示includeFilters参数的使用如下:

    在com.breakyizhan.service包下新建一个UserService2类如下:注意没有带@Service注解

    package com.breakyizhan.service;
    public class UserService2 {
    }

    配置类改成:

    @ComponentScan(value="com.breakyizhan",useDefaultFilters=true,
        includeFilters={
            @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
            @Filter(type=FilterType.ASSIGNABLE_TYPE,classes={UserService2.class})
        })
    @Configuration
    public class MainScanConfig {
    }

    运行结果如下:

    mainScanConfig
    userController
    userDao
    userService
    userService2

    userService2同样被加入到了spring容器

    新增一个自定义的实现了TypeFilter的MyTypeFilter类如下:

    /**
     * 自定义过滤
     *
     * @date 2018年5月12日
     */
    public class MyTypeFilter implements TypeFilter {
        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();
            System.out.println("--->"+className);
            // 检测名字包含Service的bean
            if(className.contains("Service")){
                return true;
            }
            return false;
        }
    }

    修改主配置如下:

    @ComponentScan(value="com.breakyizhan",useDefaultFilters=true,
        includeFilters={
            @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
            @Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})
        })
    @Configuration
    public class MainScanConfig {
    }

    运行结果如下:

    mainScanConfig
    userController
    userDao
    userService
    userService2

    可以发现同样userService2被加入到了spring容器中

    好了includeFilters参数就演示到这,另外一个参数excludeFilters和includeFilters用户一摸一样,只是他是过滤出不加入spring容器中,感兴趣的同学可以自己试试,我这边就不演示了

    @ComponentScan的常用方式如下

    • 自定扫描路径下边带有@Controller,@Service,@Repository,@Component注解加入spring容器
    • 通过includeFilters加入扫描路径下没有以上注解的类加入spring容器
    • 通过excludeFilters过滤出不用加入spring容器的类
    • 自定义增加了@Component注解的注解方式
  •   Spring注解大全
  •   本文标题:Spring注解之 @ComponentScan 的详细介绍 - Break易站
    转载请保留页面地址:https://www.breakyizhan.com/java/14641.html
      微信返利机器人
      免费:淘宝,京东,拼多多优惠券
      腾讯,爱奇艺,优酷的VIP视频免费解析,免费看
      即刻扫描二维码,添加微信机器人!

    发表笔记

    电子邮件地址不会被公开。 必填项已用*标注