https://blog.csdn.net/liuxingsiye/article/details/52171508
通常情況下我們在創建spring項目的時候在xml配置文件中都會配置這個表情,配置完這個標簽后,spring就會去自動掃描base-package對應的路徑或者該路徑的子包下面的java文件,如果掃描到文件中帶有@Service,@Component,@Repository,@Controller等這些注解的類,則把這些類注冊為bean
注:如果配置了<context:component-scan>那么<context:annotation-config/>標簽就可以不用在xml中再配置了,因為前者包含了后者。另外<context:annotation-config/>還提供了兩個子標簽 <context:include-filter>和 <context:exclude-filter>
在注解注入之前也必須在spring的配置文件中做如下配置,我們看下spring.xml文件的內容:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.sparta.trans" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
這個配置文件中必須聲明xmlns:context 這個xml命名空間,在schemaLocation中需要指定schema:
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
這個文件中beans根節點下只有一個context:component-scan節點,此節點有兩個屬性base-package屬性告訴spring要掃描的包,use-default-filters="false"表示不要使用默認的過濾器,此處的默認過濾器,會掃描包含@Service,@Component,@Repository,@Controller注解修飾的類,use-default-filters屬性的默認值為true,這就意味着會掃描指定包下標有@Service,@Component,@Repository,@Controller的注解的全部類,並注冊成bean。所以如果僅僅是在配置文件中寫<context:component-scan base-package="
com.sparta.trans"/> Use-default-filter此時為true時,那么會對base-package包或者子包下所有的java類進行掃描,並把匹配的java類注冊成bean。
所以這用情況下可以發現掃描的粒度還是挺大的,但是如果你只想掃描指定包下面的Controller,那該怎么辦?此時子標簽<context:incluce-filter>就可以發揮作用了。如下所示
<context:component-scan base-package="com.sparta.trans.controller">
<context:include-filter type="regex" expression="com\.sparta\.trans\.[^.]+(Controller|Service)"/>
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> -->
</context:component-scan>
這樣就會只掃描base-package指定下的有@Controller下的java類,並注冊成bean
注: context:component-scan節點允許有兩個子節點<context:include-filter>和<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 |
在我們的示例中,將filter的type設置成了正則表達式,regex,注意在正則里面.表示所有字符,而\.才表示真正的.字符。我們的正則表示以Controller或者Service結束的類。
我們也可以使用annotaion來限定,如上面注釋掉的所示。這里我們指定的include-filter的type是annotation,expression則是注解類的全名。
但是因為use-dafault-filter在上面並沒有指定,默認就為true,所以當把上面的配置改成如下所示的時候,就會產生與你期望相悖的結果(注意base-package包值得變化)
<context:component-scan base-package="com.sparta.trans">
<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配置多個包名來解決這個問題了。
另外在實際項目開發中我們可以發現在base-package指定的包中有的子包是不含有注解的,所以不用掃描,此時可以指定<context:exclude-filter>來進行過濾,說明此包不需要被掃描。所以綜上可以看出 use-dafault-filters=”false”的情況下:<context:exclude-filter>可以指定不需要掃描的路徑來排除掃描這些文件,<context:include-filter>可以指定需要掃描的路徑來進行掃描。但是由於use-dafault-filters的值默認為true,所以這一點在實際使用中還是需要注意一下的。