在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>指定扫描。

Spring -- <context:component-scan>使用说明的更多相关文章

  1. [Spring Boot] Use Component Scan to scan for Bean

    Component Scan is important concept when we want to create Bean. Currently we know what, for the cla ...

  2. Spring <context:component-scan>标签属性 use-default-filters 以及子标签 include-filter使用说明

    Spring <context:component-scan>标签作用有很多,最基本就是 开启包扫描,可以使用@Component.@Service.@Component等注解: 今天要作 ...

  3. Spring依赖注入 --- 简单使用说明

    Spring依赖注入 --- 简单使用说明 本文将对spring依赖注入的使用做简单的说明,enjoy your time! 1.使用Spring提供的依赖注入 对spring依赖注入的实现方法感兴趣 ...

  4. Spring注解Component原理源码解析

    在实际开发中,我们经常使用Spring的@Component.@Service.@Repository以及 @Controller等注解来实现bean托管给Spring容器管理.Spring是怎么样实 ...

  5. Spring context:component-scan中使用context:include-filter和context:exclude-filter

    Spring context:component-scan中使用context:include-filter和context:exclude-filter XML: <?xml version= ...

  6. Spring context:component-scan代替context:annotation-config

    Spring context:component-scan代替context:annotation-config XML: <?xml version="1.0" encod ...

  7. Spring <context:annotation-config> 与<context-component-scan> 的作用

    <context:annotation-config> 与<context-component-scan> 的作用 <context:annotation-config& ...

  8. Spring 注解@Component,@Service,@Controller,@Repository

    Spring 注解@Component,@Service,@Controller,@RepositorySpring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释, ...

  9. [转载]vs2012中使用Spring.NET报错:Spring.Context.Support.ContextRegistry 的类型初始值设定项引发异常

    学习使用Spring.NET中的时候,写了一个Demo,在运行时报了一个错误:Spring.Context.Support.ContextRegistry 的类型初始值设定项引发异常. 重新整理思绪, ...

  10. 使用web.xml方式加载Spring时,获取Spring context的两种方式

    使用web.xml方式加载Spring时,获取Spring context的两种方式: 1.servlet方式加载时: [web.xml] <servlet> <servlet-na ...

随机推荐

  1. C#与sqlserver开发问题

    最近不停的在考虑C#读取数据性能问题第一种使用ado拼接sql连接数据库第二种使用ado调用存储过程第三种使用entityframework加linq第四种使用反射IList<T> 1.从 ...

  2. HDU2473 Junk-Mail Filter 【可删除的并查集】

    HDU2473 Junk-Mail Filter Problem Description Recognizing junk mails is a tough task. The method used ...

  3. python笔记-7(shutil/json/pickle/shelve/xml/configparser/hashlib模块)

    一.shutil模块--高级的文件.文件夹.压缩包处理模块 1.通过句柄复制内容 shutil.copyfileobj(f1,f2)对文件的复制(通过句柄fdst/fsrc复制文件内容) 源码: Le ...

  4. 关于java日期

    时间戳转为yyyy-MM-dd SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String formatDa ...

  5. 【java基础】java中Object对象中的Hashcode方法的作用

    以下是关于HashCode的官方文档定义: hashcode方法返回该对象的哈希码值.支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表. hashCode  ...

  6. caddy server 几个常用插件

    1.log日志   log /var/www/log/example.log 2.目录访问   browse 3.gzip压缩   gzip 4.自主ssl证书   tls /path/ssl/exa ...

  7. quick 状态机StateMachine

    function Player:addStateMachine() self.fsm_ = {} cc.GameObject.extend(self.fsm_) :addComponent(" ...

  8. CDN初学搭建(ats)

    CDN初学搭建(ats) ats trafficserver squid 一. CDN初学搭建 准备vagrant virtualbox 内部环境测试所需包 一.vagrant创建启动虚拟机 1 mk ...

  9. XaaS简介(关于IssS,PaaS以及SaaS)

    IaaS,比较容易理解,提供了一个操作系统以及操作系统的硬件支撑:阿里云: PaaS,提供了一个平台,或者说,使用PaaS是希望能够在上面建立自己的服务/应用,同时平台会提供一些API或者工具,能够降 ...

  10. Nexus搭建私服

    什么是Nexus Nexus是一个强大的Maven仓库管理器,它极大地简化了本地内部仓库的维护和外部仓库的访问. 运行原理 本地仓库与私服处在同一个局域网中,当本地仓库没有资源时,会向私服发起请求获取 ...