Spring -- <context:component-scan>使用说明
在xml配置了这个标签后,spring可以自动去扫描base-pack下面或者子包下面的java文件,如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为bean
注意:如果配置了<context:component-scan>那么<context:annotation-config/>标签就可以不用再xml中配置了,因为前者包含了后者。另外<context:component-scan>还提供了两个子标签
<context:include-filter> 和 <context:exclude-filter>,注意,两个标签不能同时使用,然会报错
<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}' 之一开头。"
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 |
<context:include-filter type="regex" expression="com\.only\.mate\.[^.]+(Controller|Service)"/>
在我们的示例中,将filter的type设置成了正则表达式,regex,注意在正则里面.表示所有字符,而\.才表示真正的.字符。
在说明这两个子标签前,先说一下<context:component-scan>有两个属性,base-package属性告诉spring要扫描的包,use-default-filters="true"(默认为true)表示使用默认的过滤器,此处的默认过滤器,会扫描指定包下的全部的标有@Component的类以及@Component的子注解@Service,@Repository,@Controller等的类,并注册成bean。所以如果仅仅是在配置文件中这么写
<context:component-scan base-package="com.only.mate"/>
Use-default-filter此时为true那么会对base-package包或者子包下的所有的进行java类进行扫描,并把匹配的java类注册成bean。
可以发现这种扫描的粒度有点太大,如果你只想扫描指定包下面的Controller,该怎么办?。如下所示
第一种:base-package指定到Controller类的包名下
<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>指定扫描。
Spring -- <context:component-scan>使用说明的更多相关文章
- [Spring Boot] Use Component Scan to scan for Bean
Component Scan is important concept when we want to create Bean. Currently we know what, for the cla ...
- Spring <context:component-scan>标签属性 use-default-filters 以及子标签 include-filter使用说明
Spring <context:component-scan>标签作用有很多,最基本就是 开启包扫描,可以使用@Component.@Service.@Component等注解: 今天要作 ...
- Spring依赖注入 --- 简单使用说明
Spring依赖注入 --- 简单使用说明 本文将对spring依赖注入的使用做简单的说明,enjoy your time! 1.使用Spring提供的依赖注入 对spring依赖注入的实现方法感兴趣 ...
- Spring注解Component原理源码解析
在实际开发中,我们经常使用Spring的@Component.@Service.@Repository以及 @Controller等注解来实现bean托管给Spring容器管理.Spring是怎么样实 ...
- Spring context:component-scan中使用context:include-filter和context:exclude-filter
Spring context:component-scan中使用context:include-filter和context:exclude-filter XML: <?xml version= ...
- Spring context:component-scan代替context:annotation-config
Spring context:component-scan代替context:annotation-config XML: <?xml version="1.0" encod ...
- Spring <context:annotation-config> 与<context-component-scan> 的作用
<context:annotation-config> 与<context-component-scan> 的作用 <context:annotation-config& ...
- Spring 注解@Component,@Service,@Controller,@Repository
Spring 注解@Component,@Service,@Controller,@RepositorySpring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释, ...
- [转载]vs2012中使用Spring.NET报错:Spring.Context.Support.ContextRegistry 的类型初始值设定项引发异常
学习使用Spring.NET中的时候,写了一个Demo,在运行时报了一个错误:Spring.Context.Support.ContextRegistry 的类型初始值设定项引发异常. 重新整理思绪, ...
- 使用web.xml方式加载Spring时,获取Spring context的两种方式
使用web.xml方式加载Spring时,获取Spring context的两种方式: 1.servlet方式加载时: [web.xml] <servlet> <servlet-na ...
随机推荐
- C++调用SQLServer存储过程
同事手头的C++工程中涉及SQLServer数据库的操作需要优化,说是测试调用存储过程失败,提示: 要了C++的源码: 折腾半天,最终定位问题,问题不在C++的代码,而是SQLServer的存储过程要 ...
- ASP.NET网站发布时的那些坑
开发工具:VS2010,MVC4.0,SQLSERVER2008 服务器:Windows server 2012,IIS8,SQLSERVER2012 一.发布后,每个页面第一次打开都很卡,50秒或更 ...
- 用stack实现min stack
遇到个好玩的问题,就是用一个stack实现min stack,什么意思呢,就是我实现stack,但是能以O(1)的时间复杂度和空间复杂度去找到我stack里面的最小值. 常规的方法是:用一个变量存放当 ...
- 隐居网V2.0
经过一个月加班加点的努力,我们终于把隐居网V2.0版做好了(一个设计两个前端三个程序).上一版的隐居网因为经验不够底层架构没搭好(前台和后台都是),又是赶工期,导致后面越做越坑爹.所谓从哪里跌倒从哪里 ...
- 数位DP新识
简单题:HDU2089 HDU3652 HDU4734 HDU3555 POJ3252 HigoCoder1033(需要前导0,或者用方法4) 总结: 1,dfs(pos,state, ...
- SmartSql 动态仓储
动态代理仓储 SmartSql源码:https://github.com/Ahoo-Wang/SmartSql 简介 动态代理仓储(SmartSql.DyRepository)组件是SmartSql非 ...
- #ifndef/#define/#endif以及#if defined/#else/#endif使用详解
1.#ifndef_WINDOWS_PLAYM4_H_ #define _WINDOWS_PLAYM4_H_ #endif 问题:想必很多人都看过"头文件中的 #ifndef/#d ...
- Cucumber 使用例子
1. junit 配置 @RunWith(Cucumber.class) @CucumberOptions(format ={"pretty","html:target/ ...
- 通俗讲讲FPGA
通俗讲讲什么是FPGA. FPGA出现之前,所有集成电路都可以看成雕塑家,但是雕成一个成品,往往要浪费很多半成品和原料,这就是ASIC的制造. 后来FPGA出现了,FPGA就是块橡皮泥,什么硬件电路都 ...
- (转)win7+iis7.5+asp.net下 CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files 解决方案
本文转载自:http://www.cnblogs.com/finesite/archive/2011/01/28/1946940.html 网上搜的解决方案但在我的环境下仍旧没有解决,我的方法如下: ...