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 实现两屏幕互相滑动
Android 实现两屏幕互相滑动 下文来自: http://blog.csdn.net/song_shi_chao/article/details/7081664 ----------------- ...
- Android学习笔记之Activity详解
1 理解Activity Activity就是一个包含应用程序界面的窗口,是Android四大组件之一.一个应用程序可以包含零个或多个Activity.一个Activity的生命周期是指从屏幕上显示那 ...
- 20179223《Linux内核原理与分析》第十周学习笔记
课本第17.19和20章内容学习 关于设备驱动和设备管理,Linux主要有四种内核成分 设备类型:在所有Unix系统中为了统一普通设备的操作所采用的分类. 模块:Linux内核中用于按需加载和卸载目标 ...
- 剑指offer第四章
剑指offer第四章 1.二叉树的镜像 二叉树的镜像:输入一个二叉树,输出它的镜像 分析:求树的镜像过程其实就是在遍历树的同时,交换非叶结点的左右子结点. 求镜像的过程:先前序遍历这棵树的每个结点,如 ...
- 《DSP using MATLAB》示例Example 8.15
- MySQL事物回滚
#commit.rollback用来确保数据库有足够的剩余空间:#commi.rollback只能用于DML操作,即insert.update.delet;#rollback操作撤销上一个commit ...
- ballerina 学习九 Client endpoints
说白了就是连接外部服务的,可以是http jms websocket .... 简单例子 代码 import ballerina/http; import ballerina/log; endpoin ...
- 【深度学习笔记】Anaconda及开发环境搭建
在学习了一段时间台大李宏毅关于deep learning的课程,以及一些其他机器学习的书之后,终于打算开始动手进行一些实践了. 感觉保完研之后散养状态下,学习效率太低了,于是便想白天学习,晚上对白天学 ...
- 安装Zookeeper(集群版)
一.环境介绍(3台虚拟机) IP Hostname 192.168.2.14 javaweb04 192.168.2.15 javaweb05 192.168.2.16 javaweb06 二.配置文 ...
- 揭晓UX(用户体验)最大的秘密
我是佩恩和特勒的粉丝已经多年了.我第一次在现实中看到他们是在上个月,被他们的表演完全迷住了. 我真的很喜欢佩恩和特勒,他们经常“回拉窗帘”,并揭示他们是怎么完成他们的魔法.其他魔术师营造神秘主义和虚假 ...