context:component-scan标签的use-default-filters属性的作用以及原理分析
一、背景
我们在Spring+SpringMVC+Mybatis的集成开发中,经常会遇到事务配置不起作用等问题,那么本文就来分析下出现这种问题可能的原因以及解决方式。
二、分析及原理窥探
1.项目结构

2.我们在spring-mvc.xml文件中进行如下配置,这种方式会成功扫描到带有@Controller注解的Bean,不会扫描带有@Service/@Repository注解的Bean,是正确的。
<context:component-scan base-package="com.hafiz.www.controller">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
3.但是如下方式,不仅仅扫描到带有@Controller注解的Bean,还扫描到带有@Service/@Repository注解的Bean,可能造成事务不起作用等问题。
<context:component-scan base-package="com.hafiz.www">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
这是因为什么呢?下面让我们来从源码进行分析。
1.<context:component-scan>会交给org.springframework.context.config.ContextNamespaceHandler处理.
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来调用如下代码:
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类是否是合法的:
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 进行白名单过滤,否则默认排除。
三、结论
在spring-mvc.xml中进行如下配置:
<context:component-scan base-package="com.hafiz.www">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
则SpringMVC容器不仅仅扫描并注册带有@Controller注解的Bean,而且还扫描并注册了带有@Component的子注解@Service、@Reposity的Bean。因为use-default-filters默认为true。所以如果不需要默认的,则use-default-filters=“false”禁用掉。
当我们进行上面的配置时,SpringMVC容器会把service、dao层的bean重新加载,从而造成新加载的bean覆盖了老的bean,但事务的AOP代理没有配置在spring-mvc.xml配置文件中,造成事务失效。解决办法是:在spring-mvc.xml配置文件中的context:component-scan标签中使用use-default-filters=“false”禁用掉默认的行为。
context:component-scan标签的use-default-filters属性的作用以及原理分析的更多相关文章
- component-scan标签的use-default-filters属性的作用以及原理分析
一.背景 我们在Spring+SpringMVC+Mybatis的集成开发中,经常会遇到事务配置不起作用等问题,有时候就是因为包扫描出了问题,其中component-scan的标签的use-def ...
- HTML5 script 标签的 crossorigin 和integrity属性的作用
Bootstrap 4 依赖的基础库中出现了两个新的属性 <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.slim.m ...
- [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 ...
- 在Asp.Net MVC中实现RequiredIf标签对Model中的属性进行验证
在Asp.Net MVC中可以用继承ValidationAttribute的方式,自定制实现RequiredIf标签对Model中的属性进行验证 具体场景为:某一属性是否允许为null的验证,要根据另 ...
- CompareValues标签对Model中的属性进行验证
在Asp.Net MVC中实现CompareValues标签对Model中的属性进行验证 在Asp.Net MVC中可以用继承ValidationAttribute的方式,自定制实现Model两个 ...
- HTML5中常用的标签(及标签的属性和作用)
1.标签:<!DOCTYPE>作用:声明是文档中的第一成分,位于<html>标签之前. 2.标签:<html>作用:此元素可告知浏览器其自身是一个HTML文档.属性 ...
- HTML <img> 标签的 height 和 width 属性
定义和用法 <img> 标签的 height 和 width 属性设置图像的尺寸. 提示:为图像指定 height 和 width 属性是一个好习惯.如果设置了这些属性,就可以在页面加载时 ...
- html的标签中 unselectable=on 属性的作用
在IE浏览器中,当input获得焦点时,点击有unselectable="on"属性的标签时,不会触发onblur事件. 加上该属性的元素不能被选中. < !DOCTYPE ...
- HTML的iframe标签妙用 - 在线执行前端代码的网站原理是什么?
在我自己的日常前端开发中,其实iframe标签出现的次数并不是很多.作为一个很古老(浏览器兼容性非常好)的标签,有必要去了解一下它的典型应用场景. (图片说明:所有浏览器都支持iframe,无论什么版 ...
随机推荐
- Android——Adapter
Adapter——本身只是一个接口.Adapter是将数据绑定到UI界面上的桥接类.Adapter负责创建显示每个项目的子View和提供对下层数据的访问. 数据适配器作用:把复杂的数据(数组.链表.数 ...
- c# 判断访问来源是否来自手机
public Boolean IsMobileDevice() { string[] mobileAgents =new []{ "iphone", "android&q ...
- 【codeforces 696B】 Puzzles
http://codeforces.com/problemset/problem/696/B (题目链接) 题意 给出一棵树,随机dfs遍历这棵树,求解每个节点的期望dfs序. Solution 考虑 ...
- Java防止SQL注入(转)
一.SQL注入简介 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库. 二.SQL注入攻击的总体 ...
- html中用div代替textarea实现输入框高度随输入内容变化
项目中的需求:留言栏输入高度变化,超过1行时,自动伸展,超过4行后,不再伸展.主要思想是利用最小高度和最大高度,再加上overflow来实现,到了最大高度,文字不会溢出而是隐藏.根据文本框中字体的大小 ...
- python安装、模块安装
python安装 windows 下载安装包 https://www.python.org/downloads 改环境变量 [右键计算机]-->[属性]-->[高级系统设置]-->[ ...
- Android File存储
原创文章,转载请注明出处:http://www.cnblogs.com/baipengzhan/p/Android_File_store.html 一 概念 Android系统中提供了一种文件读写的方 ...
- ReportServices如何在一页中将报表分成两列显示
创建两个数据集 DataSet1 DataSet2 DataSet1 SELECT TOP (SELECT (COUNT(*) + 1) / 2 A ...
- 如何获得Webapp的根项目路径 即ServletContext.getRealPath() 的输入参数要以"/"开头
ServletContext.getRealPath() 的输入参数要以"/"开头 2014-03-26 15:54 5738人阅读 评论(1) 收藏 举报 版权声明:本文为博主原 ...
- python和数据科学(Anaconda)
Python拥有着极其丰富且稳定的数据科学工具环境.遗憾的是,对不了解的人来说这个环境犹如丛林一般(cue snake joke).在这篇文章中,我会一步一步指导你怎么进入这个PyData丛林. 你可 ...