Spring -- 使用说明

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