一、背景

​ 我们在Spring+SpringMVC+Mybatis的集成开发中,经常会遇到事务配置不起作用等问题,有时候就是因为包扫描出了问题,其中component-scan的标签的use-default-filters属性坑了很多人,那么本文就来分析下出现这种问题可能的原因以及解决方式。

二、分析及原理窥探

项目结构

我们在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>

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

<context:component-scan base-package="com.hafiz.www"></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”禁用掉默认的行为。

component-scan标签的use-default-filters属性的作用以及原理分析的更多相关文章

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

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

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

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

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

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

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

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

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

  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 <script> 标签的 defer 和 async 属性

    HTMKL <script>标签中有defer和async属性,简单介绍一下两者的区别吧.   普通的script标签会让浏览器立即下载并执行完毕,执行也是按照先后顺序,再进行后面的解析. ...

随机推荐

  1. Unity 4.7 导出工程在XCode10.1上编译报错

    Unity 4.7 导出工程在XCode 10.1上编译报错,而在XCode 9.3上是可以正常编译运行的.原因是Unity4.7所依赖的头文件和库文件在XCode10上没有了,解决办法如下,把XCo ...

  2. duplicate symbol _OBJC_IVAR

    duplicate symbol _OBJC_IVAR - Kingdev - 博客园 代码合并问题 git合并提示冲突文件为project.pbxproj,先去掉所有冲突提示<<< ...

  3. python3 datetime和time获取当前日期和时间

    import datetime import time # 获取当前时间, 其中中包含了year, month, hour, 需要import datetime today = datetime.da ...

  4. react脚手架环境搭建流程

    1.安装与配置node.js:1.1软件下载地址:https://nodejs.org/en/,推荐下载.msi文件,其中npm已经集成在了node.js中.1.2 双击下载的.msi文件进行安装,安 ...

  5. Delphi XE7调用Java Class,JAR

    Delphi XE5,XE6需要用户手工编译并将Classes.Dex加入到包中,不过Delphi XE7可以省掉这些工作了. 如何在XE7中调用Java,具体步骤如下: 1.将jar文件添加到XE7 ...

  6. hadoop分布式安装及其集群配置笔记

    各机器及角色信息: 共10台机器,hostname与ip地址映射在此不做赘述.此为模拟开发环境安装,所以不考虑将NameNode和SecondaryNameNode安装在同一台机器. 节点 角色 na ...

  7. Python基础学习笔记(一)安装以及IDE的配置

    一.初识Python Python官方网站:www.python.org 版本:python-3.4.3.amd64 初次接触Python,没有使用Python 2.x进行开发真实项目的经历.所以不知 ...

  8. nRF52832 BLE_DFU空中升级OTA(二)编译下载(SDK14.2.0)

    上一篇配置好了开发环境,现在就可以试着跑一下例程了,这里需要两个例程,一个是bootloader的,一个是应用程序的,其路径分别为: bootloader:SDK_14.2.0工程\examples\ ...

  9. ruby Rspec+jenkins+allure持续集成

    1.Allure2使用说明 2.ruby下载allure的gem gem install allure-rspec 3.修改源码 C:\Ruby23-x64\lib\ruby\gems\2.3.0\g ...

  10. Gblocks命令行

    使用默认的设置: $ Gblocks proteins.fasta -t=p 必须是 fasta 文件在前,参数在后.若没有参数,则进入交互式界面. Gblocks cds.fasta −t=c −b ...