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