• Spring -- <context:component-scan>使用说明


      在xml配置了这个标签后,spring可以自动去扫描base-pack下面或者子包下面的java文件,如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为bean

    注意:如果配置了<context:component-scan>那么<context:annotation-config/>标签就可以不用再xml中配置了,因为前者包含了后者。另外<context:component-scan>还提供了两个子标签

      <context:include-filter> 和 <context:exclude-filter>,注意,两个标签不能同时使用,然会报错

    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>

      错误信息:"发现了以元素 'context:include-filter' 开头的无效内容。应以 '{"http://www.springframework.org/schema/context":exclude-filter}' 之一开头。"

    filter标签的type和表达式说明如下:

     Filter Type Examples Expression Description
    annotation org.example.SomeAnnotation 符合SomeAnnoation的target class
    assignable org.example.SomeClass 指定class或interface的全名
    aspectj org.example..*Service+ AspectJ語法
    regex org.example.Default.* Regelar Expression
    custom org.example.MyTypeFilter Spring3新增自訂Type,實作org.springframework.core.type.TypeFilter

     

    <context:include-filter type="regex" expression="com.only.mate.[^.]+(Controller|Service)"/>

      在我们的示例中,将filter的type设置成了正则表达式,regex,注意在正则里面.表示所有字符,而.才表示真正的.字符。

     

      在说明这两个子标签前,先说一下<context:component-scan>有两个属性,base-package属性告诉spring要扫描的包,use-default-filters="true"(默认为true)表示使用默认的过滤器,此处的默认过滤器,会扫描指定包下的全部的标有@Component的类以及@Component的子注解@Service,@Repository,@Controller等的类,并注册成bean。所以如果仅仅是在配置文件中这么写

    <context:component-scan base-package="com.only.mate"/>

     Use-default-filter此时为true那么会对base-package包或者子包下的所有的进行java类进行扫描,并把匹配的java类注册成bean。

     

     可以发现这种扫描的粒度有点太大,如果你只想扫描指定包下面的Controller,该怎么办?。如下所示

    第一种:base-package指定到Controller类的包名下

    <context:component-scan base-package="com.only.mate.controller" /> 

     这样扫描base-package(这个包下只有Controller注释的类)下的类,并注册成bean。

    第二种:如下所示

    (推荐这样的方式)
    <
    context:component-scan base-package="com.only.mate" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>

    这样就会只扫描base-package指定下的有@Controller下的java类,并注册成bean。

    或则

    <context:component-scan base-package="com.only.mate" use-default-filters="true">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
    </context:component-scan>

    这样就会只扫描base-package指定下的除了@Service下的java类,并注册成bean。

    特别要注意的是:

    如果将第二种方法的use-dafault-filter改为相反的值,就会产生与你期望相悖的结果

    如下所示:

    <context:component-scan base-package="com.only.mate" use-default-filters="true">  
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   
    </context:component-scan>

    此时,spring不仅扫描了@Controller,还扫描了指定包所在的子包service包下注解@Service的java类,此时指定的include-filter没有起到作用。

    只要把use-default-filter设置成false就可以了。这样就可以避免在base-packeage配置多个包名这种不是很优雅的方法来解决这个问题了。

     

    <context:component-scan base-package="com.only.mate" use-default-filters="false">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
    </context:component-scan>

    “No mapping found for HTTP request with URI [/SpringMVC/user/index] in DispatcherServlet with name 'springServlet'”,没有扫描Controller注解。

     


    为什么会出现这样的结果呢?

      关键在于use-default-filters的值决定扫描的注解类型,这里又要提到这个属性的作用了。

      use-default-filters="true"(默认为true)表示使用默认的过滤器,此处的默认过滤器,会扫描指定包下的全部的标有@Component的类以及@Component的子注解@Service,@Repository,@Controller等的类,并注册成bean。

    具体分析如下:

    <context:component-scan base-package="com.only.mate" use-default-filters="true">  
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   
    </context:component-scan>

    这种情况use-default-filters="true",默认会扫描包含Service,Component,Repository,Controller注解修饰的类,我们加上了<context:include-filter>标签后,也只是说增加扫描类型,再原有的基础上在增加,所以这样会扫描包含Service,Component,Repository,Controller注解修饰的类以及自己新增的类型的类。(注意:这里会重复扫描Service注解,从而导致事务失效

     

     

    <context:component-scan base-package="com.only.mate" use-default-filters="false"> 
      <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
    </context:component-scan>

     

    这种情况use-default-filters="false",所以不会扫描任何类,我们加上了<context:exclude-filter>标签后,也只是说过滤扫描类型,再原有的基础上在减少,所以这样依然没有扫描任何类,所以当启动项目访问的时候会出现“No mapping found for HTTP request with URI [/SpringMVC/user/index] in DispatcherServlet with name 'springServlet'”,说明没有扫描Controller注解。

     

     

    综上所述:

      首先要考虑Use-dafault-filters值的设置,然后在考虑使用<context:exclude-filter>指定不扫描和<context:include-filter>指定扫描

     

  • 相关阅读:
    python操作redis
    Redis 安装试用
    python操作RabbitMQ
    pycharm快捷键
    各种python使用的坑
    RabbitMQ安装和使用
    Moosefs基本概念
    mesos客户端重新注册导致容器状态为staged
    初学Android 二 创建项目以及目录结构
    【杭电】[5631]Rikka with Graph
  • 原文地址:https://www.cnblogs.com/onlymate/p/7802122.html
Copyright © 2020-2023  润新知