http://www.iteye.com/problems/66133
<mvc:annotation-driven/>相當于注冊了DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter兩個bean,配置一些messageconverter。即解決了@Controller注解的使用前提配置。 <context:annotation-config/>是對包進行掃描,實現注釋驅動Bean定義,同時將bean自動注入容器中使用。即解決了@Controller標識的類的bean的注入和使用。 一開始我在寫配置的時候,只寫了<context:component-scan/>,并沒有使用<mvc:annotation-driven/>,servlet攔截*.do,.do請求可以被正確捕捉和處理。代碼如下 mvc-servlet.xml
Java代碼 ?
<context:component-scan?base-package ="com" ></context:component-scan>??
<context:component-scan base-package="com"></context:component-scan>
web.xml
Java代碼 ?
<servlet> ?? ????<servlet-name>mvc</servlet-name> ?? ????<servlet-class >org.springframework.web.servlet.DispatcherServlet</servlet-class > ?? ????<load-on-startup>1 </load-on-startup> ?? </servlet> ?? <servlet-mapping> ?? ????<servlet-name>mvc</servlet-name> ?? ????<url-pattern>*.do </url-pattern> ?? </servlet-mapping>??
<servlet><servlet-name>mvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>mvc</servlet-name><url-pattern>*.do</url-pattern>
</servlet-mapping>
后來為了解決靜態資源訪問的問題,servlet改成了攔截所有請求,即/,并添加了默認的servlet,這時候*.do請求不能被控制器捕捉了,頁面錯誤為404。直到添加了<mvc:annotation-driven/>之后,.do請求才又能被正確捕捉和處理。代碼如下 mvc-servlet.xml
Java代碼 ?
<context:component-scan?base-package ="com" ></context:component-scan> ?? <mvc:annotation-driven/> ?? <mvc:resources?mapping="/styles/**" ?location="/WEB-INF/resource/styles/" /> ?? <mvc:default -servlet-handler/>??
<context:component-scan base-package="com"></context:component-scan>
<mvc:annotation-driven/>
<mvc:resources mapping="/styles/**" location="/WEB-INF/resource/styles/"/>
<mvc:default-servlet-handler/>
web.xml
Java代碼 ?
<servlet> ?? ????<servlet-name>mvc</servlet-name> ?? ????<servlet-class >org.springframework.web.servlet.DispatcherServlet</servlet-class > ?? ????<load-on-startup>1 </load-on-startup> ?? </servlet> ?? <servlet-mapping> ?? ????<servlet-name>mvc</servlet-name> ?? ????<url-pattern>/</url-pattern> ?? </servlet-mapping>??
<servlet><servlet-name>mvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>mvc</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>
是什么原因造成這種區別的呢?為什么一開始沒用<mvc:annotation-driven/>的時候可以,添加了默認servlet之后就不行了呢?
?
最后的配置如果沒有<mvc:annotation-driven/>,那么所有的Controller可能就沒有解析,所有當有請求時候都沒有匹配的處理請求類,就都去<mvc:default-servlet-handler/>即default servlet處理了。添加上<mvc:annotation-driven/>后,相應的do請求被Controller處理,而靜態資源因為沒有相應的Controller就會被default servlet處理??傊疀]有相應的Controller就會被default servlet處理就ok了。
?
=====http://www.cnblogs.com/shines77/p/3315445.html
mvc:annotation-driven是一種簡寫的配置方式,那么mvc:annotation-driven到底做了哪些工作呢?如何替換掉mvc:annotation-driven呢?
<mvc:annotation- driven/>在初始化的時候會自動創建兩個對 象,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter 和 org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter, 我們如果想不使用<mvc:annotation-driven/>這種簡寫方式,將其替換掉的話,就必須自己手動去配置這兩個bean對 象。下面是這兩個對象的配置方法,和詳細的注視說明。
?
==========http://jinnianshilongnian.iteye.com/blog/1762632
context:component-scan掃描使用上的容易忽略的use-default-filters
?
問題
如下方式可以成功掃描到@Controller注解的Bean,不會掃描@Service/@Repository的Bean。正確
?
Java代碼 ?
?<context:component-scan?base-package ="org.bdp.system.test.controller" >? ?? ?????<context:include-filter?type="annotation" ?expression="org.springframework.stereotype.Controller" />? ?? </context:component-scan>??
<context:component-scan base-package="org.bdp.system.test.controller"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
??
但是如下方式,不僅僅掃描@Controller,還掃描 @Service/@Repository的Bean,可能造成一些問題
?
Java代碼 ?
?<context:component-scan?base-package ="org.bdp" >? ?? ?????<context:include-filter?type="annotation" ?expression="org.springframework.stereotype.Controller" />? ?? </context:component-scan>??
<context:component-scan base-package="org.bdp"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
?
這個尤其在springmvc+spring+hibernate等集成時最容易出問題的地,最典型的錯誤就是:
事務不起作用
?
這是什么問題呢?
分析
1、<context:component-scan>會交給org.springframework.context.config.ContextNamespaceHandler處理;
?
Java代碼 ?
registerBeanDefinitionParser("component-scan" ,?new ?ComponentScanBeanDefinitionParser());??
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
?
2、ComponentScanBeanDefinitionParser會讀取配置文件信息并組裝成org.springframework.context.annotation.ClassPathBeanDefinitionScanner進行處理;
3、如果沒有配置<context:component-scan>的use-default-filters屬性,則默認為true,在創建ClassPathBeanDefinitionScanner時會根據use-default-filters是否為true來調用如下代碼:
?
Java代碼 ?
??protected ?void ?registerDefaultFilters()?{ ?? this .includeFilters.add(new ?AnnotationTypeFilter(Component.class )); ??ClassLoader?cl?=?ClassPathScanningCandidateComponentProvider.class .getClassLoader(); ?? try ?{ ??????this .includeFilters.add(new ?AnnotationTypeFilter( ?? ????????????((Class<??extends ?Annotation>)?cl.loadClass("javax.annotation.ManagedBean" )),?false )); ?? ????logger.info("JSR-250?'javax.annotation.ManagedBean'?found?and?supported?for?component?scanning" ); ?? } ?? catch ?(ClassNotFoundException?ex)?{ ???????? } ?? try ?{ ??????this .includeFilters.add(new ?AnnotationTypeFilter( ?? ????????????((Class<??extends ?Annotation>)?cl.loadClass("javax.inject.Named" )),?false )); ?? ????logger.info("JSR-330?'javax.inject.Named'?annotation?found?and?supported?for?component?scanning" ); ?? } ?? catch ?(ClassNotFoundException?ex)?{ ???????? } ??
protected void registerDefaultFilters() {this.includeFilters.add(new AnnotationTypeFilter(Component.class));ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();try {this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) cl.loadClass("javax.annotation.ManagedBean")), false));logger.info("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.}try {this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) cl.loadClass("javax.inject.Named")), false));logger.info("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-330 API not available - simply skip.}}
?
?
可以看到默認ClassPathBeanDefinitionScanner會自動注冊對@Component、@ManagedBean、@Named注解的Bean進行掃描。如果細心,到此我們就找到問題根源了。
?
?
4、在進行掃描時會通過include-filter/exclude-filter來判斷你的Bean類是否是合法的:
?
Java代碼 ?
protected ?boolean ?isCandidateComponent(MetadataReader?metadataReader)?throws ?IOException?{ ??????for ?(TypeFilter?tf?:?this .excludeFilters)?{ ?? ????????if ?(tf.match(metadataReader,?this .metadataReaderFactory))?{ ?? ????????????return ?false ; ?? ????????} ?? ????} ?? ????for ?(TypeFilter?tf?:?this .includeFilters)?{ ?? ????????if ?(tf.match(metadataReader,?this .metadataReaderFactory))?{ ?? ????????????AnnotationMetadata?metadata?=?metadataReader.getAnnotationMetadata(); ?? ????????????if ?(!metadata.isAnnotated(Profile.class .getName()))?{ ?? ????????????????return ?true ; ?? ????????????} ?? ????????????AnnotationAttributes?profile?=?MetadataUtils.attributesFor(metadata,?Profile.class ); ?? ????????????return ?this .environment.acceptsProfiles(profile.getStringArray("value" )); ?? ????????} ?? ????} ?? ????return ?false ; ?? }??
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {for (TypeFilter tf : this.excludeFilters) {if (tf.match(metadataReader, this.metadataReaderFactory)) {return false;}}for (TypeFilter tf : this.includeFilters) {if (tf.match(metadataReader, this.metadataReaderFactory)) {AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();if (!metadata.isAnnotated(Profile.class.getName())) {return true;}AnnotationAttributes profile = MetadataUtils.attributesFor(metadata, Profile.class);return this.environment.acceptsProfiles(profile.getStringArray("value"));}}return false;}
?
即
首先通過exclude-filter 進行黑名單過濾;
然后通過include-filter?進行白名單過濾;
否則默認排除。
?
結論
Java代碼 ?
<context:component-scan?base-package ="org.bdp" >? ?? ?????<context:include-filter?type="annotation" ?expression="org.springframework.stereotype.Controller" />? ?? </context:component-scan>??
<context:component-scan base-package="org.bdp"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
?
為什么這段代碼不僅僅掃描@Controller注解的Bean,而且還掃描了@Component的子注解@Service、@Reposity。因為use-default-filters默認為true。所以如果不需要默認的,則use-default-filters=“false”禁用掉。
?
?
請參考
《SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常見問題總結》?
《第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC》中的ContextLoaderListener初始化的上下文和DispatcherServlet初始化的上下文關系。
?
如果在springmvc配置文件,不使用cn.javass.demo.web.controller前綴,而是使用cn.javass.demo,則service、dao層的bean可能也重新加載了,但事務的AOP代理沒有配置在springmvc配置文件中,從而造成新加載的bean覆蓋了老的bean,造成事務失效。只要使用use-default-filters=“false”禁用掉默認的行為就可以了。
?
問題不難,spring使用上的問題??偨Y一下方便再遇到類似問題的朋友參考。
?
?
========================
http://my.oschina.net/u/1012289/blog/129298
自己看了官方文檔,也到網上查了下,目前理解如下: ? <context:component-scan/>和<mvc:annotation-driven/>: <mvc:annotation-driven/>相當于注冊了DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter兩個bean,配置一些messageconverter。即解決了@Controller注解的使用前提配置。? <context:annotation-config/>是對包進行掃描,實現注釋驅動Bean定義,同時將bean自動注入容器中使用。即解決了@Controller標識的類的bean的注入和使用。? 一開始我在寫配置的時候,只寫了<context:component-scan/>,并沒有使用<mvc:annotation-driven/>,servlet攔截*.do,.do請求可以被正確捕捉和處理。代碼如下? mvc-servlet.xml?
Java代碼?? <context:component-scan?base- package = "com" ></context:component-scan>??
web.xml?
Java代碼?? <servlet>?? ????<servlet-name>mvc</servlet-name>?? ????<servlet- class >org.springframework.web.servlet.DispatcherServlet</servlet- class >?? ????<load-on-startup> 1 </load-on-startup>?? </servlet>?? <servlet-mapping>?? ????<servlet-name>mvc</servlet-name>?? ????<url-pattern>*. do </url-pattern>?? </servlet-mapping>??
后來為了解決靜態資源訪問的問題,servlet改成了攔截所有請求,即/,并添加了默認的servlet,這時候*.do請求不能被控制器捕捉了,頁面錯誤為404。直到添加了<mvc:annotation-driven/>之后,.do請求才又能被正確捕捉和處理。代碼如下? mvc-servlet.xml?
Java代碼?? <context:component-scan?base- package = "com" ></context:component-scan>?? <mvc:annotation-driven/>?? <mvc:resources?mapping= "/styles/**" ?location= "/WEB-INF/resource/styles/" />?? <mvc: default -servlet-handler/>??
web.xml?
Java代碼?? <servlet>?? ????<servlet-name>mvc</servlet-name>?? ????<servlet- class >org.springframework.web.servlet.DispatcherServlet</servlet- class >?? ????<load-on-startup> 1 </load-on-startup>?? </servlet>?? <servlet-mapping>?? ????<servlet-name>mvc</servlet-name>?? ????<url-pattern>/</url-pattern>?? </servlet-mapping>??
是什么原因造成這種區別的呢?為什么一開始沒用<mvc:annotation-driven/>的時候可以,添加了默認servlet之后就不行了呢? <context:annotation-config/>和 <context:component-scan/>:
在基于主機方式配置 Spring 的配置文件中,你可能會見到 <context:annotation-config/> 這樣一條配置,他的作用是式地向 ?Spring? 容器注冊
AutowiredAnnotationBeanPostProcessor 、 CommonAnnotationBeanPostProcessor 、
PersistenceAnnotationBeanPostProcessor? 以及 ?RequiredAnnotationBeanPostProcessor? 這 ?4? 個 BeanPostProcessor 。
注冊這 4 個 ? BeanPostProcessor 的作用,就是為了你的系統能夠識別相應的注解。
例如:
如果你想使用 @Autowired 注解,那么就必須事先在 ?Spring? 容器中聲明 ?AutowiredAnnotationBeanPostProcessor Bean 。傳統聲明方式如下
< bean ? class = "org.springframework.beans.factory.annotation.?AutowiredAnnotationBeanPostProcessor?" /> ?
如果想使用 @ Resource? 、 @ PostConstruct 、 @ PreDestroy 等注解就必須聲明 CommonAnnotationBeanPostProcessor
如果想使用 @PersistenceContext 注解,就必須聲明 PersistenceAnnotationBeanPostProcessor 的 Bean 。
如果想使用 ?@Required 的注解,就必須聲明 RequiredAnnotationBeanPostProcessor 的 Bean 。同樣,傳統的聲明方式如下:
< bean ? class = "org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" /> ?
一般來說,這些注解我們還是比較常用,尤其是 Antowired 的注解,在自動注入的時候更是經常使用,所以如果總是需要按照傳統的方式一條一條配置顯得有些繁瑣和沒有必要,于是 spring 給我們提供 <context:annotation-config/> 的簡化配置方式,自動幫你完成聲明。
???不過,呵呵, 我們使用注解一般都會配置 掃描包路徑選項
< context:component-scan ? base-package =”XX.XX” /> ?
???? 該配置項其實也包含了自動注入上述 processor 的功能,因此當使用 ?<context:component-scan/>? 后,就可以將 ?<context:annotation-config/>? 移除了。
?
?
?
總結
以上是生活随笔 為你收集整理的context:component-scan/和mvc:annotation-driven/的区别 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。