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 ...
随机推荐
- Android中的关于MDM中的几个方法举例
Android中的关于MDM中的几个方法举例 首先介绍一下MDM是什么的缩写,MDM是什么? MDM 是 (Mobile Device Management )的缩写,中文翻译过来就是移动设备管理.随 ...
- 《DSP using MATLAB》示例Example 6.27
代码: % r = 0.9; theta = (pi/180)*[-55:5:-35, 35:5:55]'; p = r*exp(j*theta); a = poly(p); b = 1; w = [ ...
- LeetCode My Calendar I
原题链接在这里:https://leetcode.com/problems/my-calendar-i/description/ 题目: Implement a MyCalendar class to ...
- webpack 图片资源处理
备注: css 引用图片资源 1. 安装loader yarn add file-loader --dev 2. 配置 const path = require("path"); ...
- python 与时间有关的操作
python保存时间戳文件 import time # ISOTIMEFORMAT='%Y-%m-%d %X' ISOTIMEFORMAT='%Y-%m-%d' t= time.strftime( I ...
- 浅谈splay
\(BST\) 二叉查找树,首先它是一颗二叉树,其次它里面每个点都满足以该点左儿子为根的子树里结点的值都小于自己的值,以该点右儿子为根的子树里结点的值都大于自己的值.如果不进行修改,每次查询都是\(O ...
- Spring整合JavaMail
1.添加jar包 #此处省略spring基础相关jar包描述,以下是发送邮件相关jar包 <dependency> <groupId>org.springframework&l ...
- Python——str常用操作方法
1. 索引(即下标) s = 'ABCDEFGHIJKLMN' s1 = s[0] print('s[0] = ' + s1) #s[0] = A print('s[3] = '+ s[3]) #s[ ...
- RK3288 查看时钟树
主控端可以通过指令查看时钟树,enable_cnt为1,表示时钟已使能. # cat d/clk/clk_summary cat d/clk/clk_summary clock enable_cnt ...
- windows环境vagrant修改静态资源文件,centos虚拟机中nginx的web环境下不生效
最近上手krpano,本地修改了krpano.html文件或者xml文件,在虚拟机环境打开文件是修改过来了,在nginx中就是不生效. 修改nginx.conf中http{}中的 sendfile ...