在xml配置了这个标签后,spring能够自动去扫描base-pack下面或者子包下面的java文件,若是扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为beanjava
注意:若是配置了<context:component-scan>那么<context:annotation-config/>标签就能够不用再xml中配置了,由于前者包含了后者。另外<context:component-scan>还提供了两个子标签正则表达式
<context:include-filter> 和 <context:exclude-filter>,注意,两个标签不能同时使用,然会报错spring
<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}' 之一开头。"express
filter标签的type和表达式说明以下:app
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,注意在正则里面.表示全部字符,而\.才表示真正的.字符。spa
在说明这两个子标签前,先说一下<context:component-scan>有两个属性,base-package属性告诉spring要扫描的包,use-default-filters="true"(默认为true)表示使用默认的过滤器,此处的默认过滤器,会扫描指定包下的所有的标有@Component的类以及@Component的子注解@Service,@Repository,@Controller等的类,并注册成bean。因此若是仅仅是在配置文件中这么写code
<context:component-scan base-package="com.only.mate"/>
Use-default-filter此时为true那么会对base-package包或者子包下的全部的进行java类进行扫描,并把匹配的java类注册成bean。component
能够发现这种扫描的粒度有点太大,若是你只想扫描指定包下面的Controller,该怎么办?。以下所示xml
第一种:base-package指定到Controller类的包名下blog
<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>指定扫描。