context:component-scan标签的use-default-filters属性的作用以及原理分析
来源:互联网 发布:qq影像官方下载 mac 编辑:程序博客网 时间:2024/06/05 09:58
一、背景
我们在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.会交给org.springframework.context.config.ContextNamespaceHandler处理.
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
2.ComponentScanBeanDefinitionParser会读取配置文件信息并组装成org.springframework.context.annotation.ClassPathBeanDefinitionScanner进行处理。
3.如果没有配置的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属性的作用以及原理分析
- context:component-scan标签的use-default-filters属性的作用以及原理分析
- context:component-scan标签的use-default-filters属性的作用以及原理分析
- context:component-scan标签的use-default-filters属性的作用以及原理分析
- context:component-scan标签的use-default-filters属性的作用以及原理分析
- context:component-scan标签的use-default-filters属性的作用以及原理
- context:component-scan标签的use-default-filters属性
- context:component-scan标签的use-default-filters属性的作用以
- context:component-scan标签的use-default-
- context:component-scan扫描使用上的容易忽略的use-default-filters
- context:component-scan扫描使用上的容易忽略的use-default-filters
- context:component-scan扫描使用上的容易忽略的use-default-filters
- context:component-scan扫描使用上的容易忽略的use-default-filters
- context:component-scan扫描使用上的容易忽略的use-default-filters
- context:component-scan扫描使用上的容易忽略的use-default-filters
- context:component-scan扫描使用上的容易忽略的use-default-filters
- context:component-scan扫描使用上的容易忽略的use-default-filters
- springmvc配置文件中context:component-scan扫描使用上的容易忽略的use-default-filters
- display有哪些值?说明他们的作用
- 【编程初学者】创建自己的开源项目6-基于当前分支,提交归并请求到主分支(myeclipse+git)
- Python_深刻理解Python中的元类(metaclass)
- 欢迎使用CSDN-markdown编辑器
- Oracle DBLINK的创建
- context:component-scan标签的use-default-filters属性的作用以及原理分析
- uint32_t
- Intent的简介以及属性的详解
- USB的四种传输类型与端点
- Eclipse历代版本
- hololens开发笔记-DEP6957未能使用“通用身份验证”连接到设备
- C++中的STL中map用法详解
- LeetCode
- Spring中@Controller和@RestController之间的区别