博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
component-scan标签的use-default-filters属性的作用以及原理分析
阅读量:6035 次
发布时间:2019-06-20

本文共 3032 字,大约阅读时间需要 10 分钟。

一、背景

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

二、分析及原理窥探

项目结构

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

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

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

  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
    ) 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
    ) 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中进行如下配置:

    则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”禁用掉默认的行为。

转载于:https://www.cnblogs.com/xyou/p/8743057.html

你可能感兴趣的文章
在 Windows 下安装 Oracle 11g XE (Express Edition)
查看>>
ListView优化
查看>>
【原创】 PostgreSQL 实现MySQL 的auto_increment 字段
查看>>
vs2015添加vc助手
查看>>
检测点1.1
查看>>
android--------阿里 AndFix 热修复
查看>>
java springcloud版b2b2c社交电商spring cloud分布式微服务 (七)高可用的分布式配置中心(Spring Cloud Config)...
查看>>
Oozie与Coordinator调度讲解及系统时区配置与定时触发两种配置方式
查看>>
RGB_YUV_YCbCr
查看>>
tesseract 安装及使用
查看>>
优化SqlServer--数据压缩
查看>>
SharePoint 自定义WebPart之间的连接
查看>>
231. Power of Two
查看>>
control.add()
查看>>
p点到(a,b)点两所在直线的垂点坐标及p点是否在(a,b)两点所在直线上
查看>>
GridView强制换行与自动换行
查看>>
51Nod 1003 阶乘后面0的数量(数学,思维题)
查看>>
Sublime text3中配置Github
查看>>
Getting Started with iOS Development Part10:Customizing your Mobile target's Splash screen
查看>>
asp.net C# MVC 提交表单后清空表单
查看>>