一、背景

  我们在Spring+SpringMVC+Mybatis的集成开发中,经常会遇到事务配置不起作用等问题,那么本文就来分析下出现这种问题可能的原因以及解决方式。

二、分析及原理窥探

  1.项目结构

  

  2.我们在spring-mvc.xml文件中进行如下配置,这种方式会成功扫描到带有@Controller注解的Bean,不会扫描带有@Service/@Repository注解的Bean,是正确的。

  1. <context:component-scan base-package="com.hafiz.www.controller">
  2. <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  3. </context:component-scan>

  3.但是如下方式,不仅仅扫描到带有@Controller注解的Bean,还扫描到带有@Service/@Repository注解的Bean,可能造成事务不起作用等问题。

  1. <context:component-scan base-package="com.hafiz.www">
  2. <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  3. </context:component-scan>

这是因为什么呢?下面让我们来从源码进行分析。

  1.<context:component-scan>会交给org.springframework.context.config.ContextNamespaceHandler处理.

  1. 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来调用如下代码:

  1. protected void registerDefaultFilters() {
  2.   this.includeFilters.add(new AnnotationTypeFilter(Component.class));
  3.   ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
  4.   try {
  5.     this.includeFilters.add(new AnnotationTypeFilter(
  6.       ((Class<? extends Annotation>) cl.loadClass("javax.annotation.ManagedBean")), false));
  7.     logger.info("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
  8.   }
  9.   catch (ClassNotFoundException ex) {
  10.     // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
  11.   }
  12.   try {
  13.     this.includeFilters.add(new AnnotationTypeFilter(
  14.       ((Class<? extends Annotation>) cl.loadClass("javax.inject.Named")), false));
  15.     logger.info("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
  16.   }
  17.   catch (ClassNotFoundException ex) {
  18.     // JSR-330 API not available - simply skip.
  19.   }
  20. }

从以上源码我们可以看出默认ClassPathBeanDefinitionScanner会自动注册对@Component、@ManagedBean、@Named注解的Bean进行扫描。

  4.在进行扫描时会通过include-filter/exclude-filter来判断你的Bean类是否是合法的:

  1. protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
  2. for (TypeFilter tf : this.excludeFilters) {
  3. if (tf.match(metadataReader, this.metadataReaderFactory)) {
  4. return false;
  5. }
  6. }
  7. for (TypeFilter tf : this.includeFilters) {
  8. if (tf.match(metadataReader, this.metadataReaderFactory)) {
  9. AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
  10. if (!metadata.isAnnotated(Profile.class.getName())) {
  11. return true;
  12. }
  13. AnnotationAttributes profile = MetadataUtils.attributesFor(metadata, Profile.class);
  14. return this.environment.acceptsProfiles(profile.getStringArray("value"));
  15. }
  16. }
  17. return false;
  18. }

从以上源码可看出:扫描时首先通过exclude-filter 进行黑名单过滤,然后通过include-filter 进行白名单过滤,否则默认排除。

三、结论

  在spring-mvc.xml中进行如下配置:

  1. <context:component-scan base-package="com.hafiz.www">
  2. <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  3. </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属性的作用以及原理分析的更多相关文章

  1. component-scan标签的use-default-filters属性的作用以及原理分析

    一.背景 ​ 我们在Spring+SpringMVC+Mybatis的集成开发中,经常会遇到事务配置不起作用等问题,有时候就是因为包扫描出了问题,其中component-scan的标签的use-def ...

  2. HTML5 script 标签的 crossorigin 和integrity属性的作用

    Bootstrap 4 依赖的基础库中出现了两个新的属性 <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.slim.m ...

  3. [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 ...

  4. 在Asp.Net MVC中实现RequiredIf标签对Model中的属性进行验证

    在Asp.Net MVC中可以用继承ValidationAttribute的方式,自定制实现RequiredIf标签对Model中的属性进行验证 具体场景为:某一属性是否允许为null的验证,要根据另 ...

  5. CompareValues标签对Model中的属性进行验证

    在Asp.Net MVC中实现CompareValues标签对Model中的属性进行验证   在Asp.Net MVC中可以用继承ValidationAttribute的方式,自定制实现Model两个 ...

  6. HTML5中常用的标签(及标签的属性和作用)

    1.标签:<!DOCTYPE>作用:声明是文档中的第一成分,位于<html>标签之前. 2.标签:<html>作用:此元素可告知浏览器其自身是一个HTML文档.属性 ...

  7. HTML <img> 标签的 height 和 width 属性

    定义和用法 <img> 标签的 height 和 width 属性设置图像的尺寸. 提示:为图像指定 height 和 width 属性是一个好习惯.如果设置了这些属性,就可以在页面加载时 ...

  8. html的标签中 unselectable=on 属性的作用

    在IE浏览器中,当input获得焦点时,点击有unselectable="on"属性的标签时,不会触发onblur事件. 加上该属性的元素不能被选中. < !DOCTYPE ...

  9. HTML的iframe标签妙用 - 在线执行前端代码的网站原理是什么?

    在我自己的日常前端开发中,其实iframe标签出现的次数并不是很多.作为一个很古老(浏览器兼容性非常好)的标签,有必要去了解一下它的典型应用场景. (图片说明:所有浏览器都支持iframe,无论什么版 ...

随机推荐

  1. ERwin® Data Modeler介绍

    Erwin是一个非常优秀数据建模工具,详细信息请参考百科与官网,在国内关于Erwin的资料不多,最有价值的还属于2004年出版的<erwin数据建模>:其他诸如各种文库的ppt与word文 ...

  2. leetcode

    Coding on LeetCode Online Judge leetcode(leetcode website) Problems algorithms 13. Roman to Integer ...

  3. js获取手机验证码倒计时的实现

    方案一 <div class="div user-input"> <input type="number" class="code& ...

  4. Linux服务器配置多台虚拟主机

    2016年11月4日15:59:12 LAMP环境 参考:http://blog.itblood.com/nginx-same-ip-multi-domain-configuration.html 在 ...

  5. HTML5的Audio标签打造WEB音频播放器

    目前,WEB页面上没有标准的方式来播放音频文件,大多数的音频文件是使用插件来播放,而众多浏览器都使用了不同的插件.而HTML5的到来,给我们提供了一个标准的方式来播放WEB中的音频文件,用户不再为浏览 ...

  6. Base64编码【转】

    转http://www.cnblogs.com/luguo3000/p/3940197.html 开发者对Base64编码肯定很熟悉,是否对它有很清晰的认识就不一定了.实际上Base64已经简单到不能 ...

  7. variadic function 的使用

    最近在看<the c programming language> K&R 7.3章 Variable-length Argument Lists  变长参数列表, 笔记一下用法 1 ...

  8. Linux下安装 MySQL

    Ubuntu环境 使用二进制安装包安装,相对简单绿色 1.到官网下载二进制压缩包http://dev.mysql.com/downloads/mysql/ 2.选择需要的版本 目前最新为5.7.之后选 ...

  9. 为什么现在更多需要用的是 GPU 而不是 CPU,比如挖矿甚至破解密码?

    作者:Cascade链接:https://www.zhihu.com/question/21231074/answer/20701124来源:知乎著作权归作者所有,转载请联系作者获得授权. 想要理解G ...

  10. Google地图路线规划

    Google地图路线规划: 需求:给定的两点之间Google地图路径规划和详情. 代码实现: //map定义省略 var directionsDisplay = new google.maps.Dir ...