spring component-scan filter
(参考的Spring version : 4.1.6.RELEASE)
我们通常会使用component-scan来进行bean的加载,但是它里面的实现机制却是一知半解。根据原码来理解一下,可能会更加清晰。
例如,我们通常会使用如下的配置:
application.xml:
<context:component-scan base-package="com.cn.kvn.service,com.cn.kvn.config,com.baidu">
<context:include-filter type="annotation" expression="com.alibaba.dubbo.config.annotation.Service" />
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
spring-servlet.xml:
<context:component-scan base-package="com.cn.kvn.controller" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
看了下面的解释,你就能大体知道这些配置具体是怎么控制和生效的了。
- componentScan解析bean的入口为:ComponentScanBeanDefinitionParser#parse(Element element, ParserContext parserContext)
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null;
}
base-package属性告诉spring要扫描的包,use-default-filters="false"表示不要使用默认的过滤器
- configureScanner会去配置scan时的使用的filter,其中use-default-filters属性是来控制是否要使用默认的过滤器的。
(默认的过滤器会去解析base-package下的含有@Component注解的类作为bean,其中@Repository, @Service, and @Controller都是@Component的子注解,故,默认的过滤器会将它们全部解析成bean)
原码中的英文注释:(ClassPathScanningCandidateComponentProvider#ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters, Environment environment)) useDefaultFilters whether to register the default filters for the @Component, @Repository, @Service, and @Controller stereotype annotations
- 用户自定义的include-filter和exclude-filter会在ComponentScanBeanDefinitionParser#parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext)方法中被解析加载。
- 在执行Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);的时候,使用过滤器的顺序是,exclude-filter优于include-filter。
也就是说,如果同时定义了exclude-filter排除了某类(某个)bean,但是include-filter又将其包含了,则该bean不会被加载到spring容器。
ClassPathScanningCandidateComponentProvider.java
/**
* Determine whether the given class does not match any exclude filter
* and does match at least one include filter.
* @param metadataReader the ASM ClassReader for the class
* @return whether the class qualifies as a candidate component
*/
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)) {
return isConditionMatch(metadataReader);
}
}
return false;
}
附:过滤规则设置
context:component-scan节点允许有两个子节点<context:include-filter>和<context:exclude-filter>。filter标签的type和表达式说明如下:
| Filter Type | Examples Expression | Description | include-filter为例 |
| annotation | org.example.SomeAnnotation | 符合SomeAnnoation的target class |
<context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/> 表示扫描base-package下的类上加了Aspect注解的类,并注册到spring的bean容器 |
| assignable | org.example.SomeClass | 指定class或interface的全名 |
<context:include-filter type="assignable" expression="com.test.scan.StuService"/> 指定扫描StuService类作为bean |
| 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,注意在正则里面.表示所有字符,而\.才表示真正的.字符。我们的正则表示以Dao或者Service结束的类。
我们也可以使用annotaion来限定,如下:
<context:component-scan base-package="cn.outofmemory.spring" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
这里我们指定的include-filter的type是annotation,expression则是注解类的全名。
另外context:conponent-scan节点还有<context:exclude-filter>可以用来指定要排除的类,其用法和include-filter一致。
spring component-scan filter的更多相关文章
- [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 Security自定义filter重复执行问题
今天做项目的时候,发现每次拦截器日志都会打两遍,很纳闷,怀疑是Filter被执行了两遍.结果debug之后发现还真是!记录一下这个神奇的BUG! 问题描述 项目中使用的是Spring-security ...
- Spring框架之Filter应用
在web.xml中进行配置,对所有的URL请求进行过滤,就像"击鼓传花"一样,链式处理. 配置分为两种A和B. 在web.xml中增加如下内容: <filter> &l ...
- not registered via @EnableConfigurationProperties or marked as Spring component
利用@ConfigurationProperties(prefix = "")来绑定属性时报错: not registered via @EnableConfigurationPr ...
- Spring Cloud Zuul Filter 和熔断
转一篇很不错的关于Spring Cloud Zuul 相关用法的文章,基本包含常用的一些场景,另外附上实际项目中的熔断.打印请求日志和登录验证的实例. 原文地址:https://www.cnblogs ...
- spring boot: 通过filter过滤器实现中文的简体繁体字符集转换(spring boot 2.3.1)
一,为什么要使用filter来实现简繁体转换? 项目中有时会有同时支持简体和繁体两种字符集的要求, 或者搜索引擎有支持繁体输入字符的需求. 针对繁体字符的显示, 我们通常会在数据库和模板.文案配置中默 ...
- Spring Boot 使用 Filter
Filter 是 JavaEE 中 Servlet 规范的一个组件,位于包javax.servlet 中,它可以在 HTTP 请求到达 Servlet 之前,被一个或多个Filter处理. 1. 编写 ...
- Spring @ Component 的作用
1.@controller 控制器(注入服务) 2.@service 服务(注入dao) 3.@repository dao(实现dao访问) 4.@component (把普通pojo实例化到spr ...
- spring @Component
使用 @Component <context:component-scan base-package="dao" /> 虽 然我们可以通过@Autowired或@R ...
- spring security 4 filter 顺序及作用
Spring Security 有两个作用:认证和授权 一.Srping security 4 filter 别名及顺序 spring security 4 标准filter别名和顺序,因为经常要用就 ...
随机推荐
- iOS开发UI篇—Quartz2D简单使用(三)
iOS开发UI篇—Quartz2D简单使用(三) 一.通过slider控制圆的缩放 1.实现过程 新建一个项目,新建一个继承自UIview的类,并和storyboard中自定义的view进行关联. 界 ...
- js获取页面宽度高度及屏幕分辨率
网页可见区域宽:document.body.clientWidth 网页可见区域高:document.body.clientHeight 网页可见区域宽:document.body.offsetWid ...
- 关于MVC
MVC,或多或少都有听说过.这个模式在客户端程序里面比较常见.以前有人老说mvc是什么设计模式之类.至少我理解的不是.我觉得 MVC是一种模块划分方法.根据它,我们可以快速地划分单独某个模块.比如排行 ...
- Nginx反向代理关于端口的问题
Nginx反向代理关于端口的问题 http://www.cnblogs.com/likehua/p/4056625.html Nginx默认反向后的端口为80,因此存在被代理后的端口为80的问 ...
- c#用牛顿法计算根号下2的值
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- Qt之WebKit学习之绘图
void Serial::on_pushButton_clicked() { //scroll(4,0); flag_btn = true; // this->update(); //绘图绘在窗 ...
- LR接口测试手工脚本与验证脚本
Action(){ char URL[250]; char mars_cid[30]; memset(URL,0,sizeof(URL)); memset(mars_cid,0,sizeof(mars ...
- php大力力 [039节] 修改一下后台项目,同时启用印象笔记,要做的事情todo列表,记录在印象笔记,速度快一些
php大力力 [039节] 修改一下后台项目,同时启用印象笔记,要做的事情todo列表,记录在印象笔记,速度快一些
- IOS网络开发(三)
1 飞机航班查询软件 1.1 问题 NSURLConnection是IOS提供的用于处理Http协议的网络请求的类,可以实现同步请求也可以实现异步请求,本案例使用NSURLConnection类实现一 ...
- Android 学习第2课,下载 eclipse 工具
可以到http://www.ddooo.com/softdown/61745.htm 下载下来是32位与64位都有的 而且是汉化的,经测试成功,还可以,不错!