美文网首页
@ComponentScan-自动扫描组件介绍

@ComponentScan-自动扫描组件介绍

作者: 超天大圣JR | 来源:发表于2019-12-18 15:26 被阅读0次

    一、@ComponentScan注解是什么

    如果你理解了ComponentScan,你就理解了Spring是一个依赖注入(dependency injection)框架。所有的内容都是关于bean的定义及其依赖关系。
    定义Spring Beans的第一步是使用正确的注解@Component或@Service或@Repository或者@Controller
    但是,Spring不知道你定义了某个bean除非它知道从哪里可以找到这个bean
    ComponentScan做的事情就是告诉Spring从哪里找到bean
    由你来定义哪些包需要被扫描。一旦你指定了,Spring将会在被指定的包及其下级包中寻找bean
    下面分别介绍在Spring Boot项目和非Spring Boot项目(如简单的JSP/Servlet或者Spring MVC应用)中如何定义@Component Scan

    二、@ComponentScan注解的基本使用

    1.Spring Boot项目

    总结:

    • 如果你的其他包都在使用了@SpringBootApplication注解的main
      app所在的包及其下级包中,则你什么都不用做,SpringBoot会自动帮你把其他包都扫描了
    • 如果你有一些bean所在的包,不在main
      app的包及其下级包中,那么你需要手动加上@ComponentScan注解并指定那个bean所在的包

    举个例子,看下面定义的类

    package com.demo.springboot;
    
    @SpringBootApplication
    public class SpringbootApplication {
    
        public static void main(String[] args) {
            ApplicationContext applicationContext = 
                    SpringApplication.run(SpringbootApplication .class, args);
    
            for (String name : applicationContext.getBeanDefinitionNames()) {
                System.out.println(name);
            }
        }
    }
    

    类 SpringbootApplication 在com.demo.springboot包下,这个类使用了@SpringBootApplication注解,该注解定义了Spring将自动扫描包com.demo.springboot及其子包下的bean
    如果你项目中所有的类都定义在com.demo.springboot包及其子包下,那你不需要做任何事
    但假如你一个类定义在包com.demo.somethingelse下,则你需要将这个新包也纳入扫描的范围,有两个方案可以达到这个目的。

    方案1
    定义@CoponentScan(“com.demo”)
    这么做扫描的范围扩大到整个父包com.demo

    @ComponentScan(“com.demo”)
    @SpringBootApplication
    public class SpringbootApplication {
    

    方案2
    定义分别扫描两个包
    @ComponentScan({“com.demo.springboot”,”com.demo.somethingelse”})

    @ComponentScan({"com.demo.springboot","com.demo.somethingelse"})
    @SpringBootApplication
    public class SpringbootApplication {
    

    特别注意一下:如果使用了方案2,如果仅仅只写@ComponentScan({"com.demo.somethingelse"})将导致com.demo.springboot包下的类无法被扫描到(框架原始的默认扫描效果无效了)

    2.非Spring Boot项目

    在非Spring Boot项目中,我们必须显式地使用@ComponentScan注解定义被扫描的包,可以通过XML文件在应用上下文中定义或在Java代码中对应用上下文定义

    Java代码方式

    @ComponentScan({"com.demo.package1","com.demo.package2"})
    @Configuration
    public class SpringConfiguration {
    

    XML文件方式

    <context:component-scan base-package="com.demo.package1, com.demo.package2"/>
    

    三、@ComponentScan注解说明

    @ComponentScan:会自动扫描包路径下面的所有被@Controller、@Service、@Repository、@Component 注解标识的类,然后装配到Spring容器中。

    @ComponentScan的属性: value指定扫描的包,includeFilters包含那些过滤,excludeFilters不包含那些过滤,useDefaultFilters默认的过滤规则是开启的,如果我们要自定义的话是要关闭的。其中@Filters是一个过滤器的接口。

    @Filters 指过滤规则,FilterType指定过滤的规则

                FilterType.ANNOTATION:按照注解
    
                FilterType.ASSIGNABLE_TYPE:按照给定的类型;
    
                FilterType.ASPECTJ:使用ASPECTJ表达式
    
                FilterType.REGEX:使用正则指定
    
                FilterType.CUSTOM:使用自定义规则)
    
                classes指定过滤的类
    
    1.基本示例:

    创建controller:

    @Controller
    public class UserController {
    }
    

    创建service:

    @Service
    public class UserService {
    }
    

    创建dao:

    @Repository
    public class UserDao {
    }
    

    添加启动类:

    @Configuration
    @ComponentScan(value = "com.spring.annotation")
    public class ScanConfig {
     
    }
    

    测试:

        @Test
        public void test02() {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ScanConfig.class);
            String[] beanDefinitionNames = context.getBeanDefinitionNames();
            for (String name : beanDefinitionNames) {
                System.out.println(name);
            }
        }
    

    结果:

    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    
    scanConfig
    annotationConfig
    userController
    userDao
    userService
    

    可以看到对应的实体类已经注入到容器中

    2.过滤指定的注解进行注入
    • excludeFilters (排除过滤器)
    @Configuration
    @ComponentScan(value = "com.spring.annotation",excludeFilters = {
            @ComponentScan.Filter(type=FilterType.ANNOTATION,classes={Controller.class})
    })
    public class ScanConfig{
     
    }
    

    @ComponentScan.Filter 指定了过滤器的规则,FilterType.ANNOTATION 表示按注解过滤,classes指定需要过滤的注解,Controller注解被排除,classes为数组可以指定多个,重新运行结果:

    scanConfig
    annotationConfig
    userDao
    userService
    

    可以看到 原来的 userController 已经消失,说明没有被注入到容器中去

    • includeFilters (包含过滤器)
    @Configuration
    @ComponentScan(value="com.spring.annotation",
    //        excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})}
            includeFilters = {
                @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}
            )},useDefaultFilters = false
    )
    public class ScanConfig {
    }
    

    运行结果:

    scanConfig
    userController
    

    可以看到只有 被@controller注解的bean注入到容器中去。useDefaultFilters默认的过滤规则是开启的,如果我们要自定义的话是要关闭的

    相关文章

      网友评论

          本文标题:@ComponentScan-自动扫描组件介绍

          本文链接:https://www.haomeiwen.com/subject/ubhunctx.html