context:component-scan扫描使用上的容易忽略的use-default-filters

问题

如下方式可以成功扫描到@Controller注解的Bean,不会扫描@Service/@Repository的Bean。正确

Java代码  

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

但是如下方式,不仅仅扫描@Controller,还扫描@Service/@Repository的Bean,可能造成一些问题

Java代码  

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

这个尤其在springmvc+spring+hibernate等集成时最容易出问题的地,最典型的错误就是:

事务不起作用

这是什么问题呢?

分析

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

Java代码  

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

Java代码  

  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. }

可以看到默认ClassPathBeanDefinitionScanner会自动注册对@Component、@ManagedBean、@Named注解的Bean进行扫描。如果细心,到此我们就找到问题根源了。

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

Java代码  

  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 进行白名单过滤;

否则默认排除。

结论

Java代码  

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

为什么这段代码不仅仅扫描@Controller注解的Bean,而且还扫描了@Component的子注解@Service、@Reposity。因为use-default-filters默认为true。所以如果不需要默认的,则use-default-filters=“false”禁用掉。

备注:Use-default-filter此时为true那么会对base-package包或者子包下的所有的进行java类进行扫描,并把匹配的java类注册成bean。

Use-dafault-filters=”false”的情况下:<context:exclude-filter>指定的不扫描,<context:include-filter>指定的扫描.

时间: 2024-07-31 12:58:26

context:component-scan扫描使用上的容易忽略的use-default-filters的相关文章

ESA2GJK1DH1K微信小程序篇: 测试微信小程序扫描Air202上面的二维码绑定设备,并通过MQTT控制设备

前言 暂无 实现功能概要 微信小程序通过扫描GPRS上的二维码,绑定GPRS设备.然后使用小程序通过GPRS远程控制开发板上的继电器, 远程显示单片机采集的温湿度数据. 一,硬件程序 硬件程序采用基础篇 https://www.cnblogs.com/yangfengwu/p/11762609.html  的底层硬件程序 该源码已经拷贝到了当前测试目录 二,微信小程序源码 测试准备工作 一,下载单片机程序(请自行下载) 二,打开微信小程序软件,导入本节工程 三,把小程序安装到手机运行 四,调整波

SpringMVC 源代码深度解析&lt;context:component-scan&gt;(扫描和注册的注解Bean)

我们在SpringMVC开发项目中,有的用注解和XML配置Bean,这两种都各有自己的优势,数据源配置比较经常用XML配置,控制层依赖的service比较经常用注解等(在部署时比较不会改变的),我们经常比较常用的注解有@Component是通用标注,@Controller标注web控制器,@Service标注Servicec层的服务,@Respository标注DAO层的数据访问.SpringMVC启动时怎么被自动扫描然后解析并注册到Bean工厂中去(放到DefaultListableBeanF

企业安全建设之路:端口扫描(上)

0×00.业务需求 由于工作关系,最近一年来都奔走在各大安全会议,无论是公开会议,例如:ISC互联网大会.freebuf互联网大会等.还是半公开的会议,例如某SRC组织的互联网金融会等.互联网安全运维人员都在谈自己企业的运维平台是如何建立的.这里我简单用思维导图总结一下: 有一定研发能力的互联网安全团队都在建立自己的安全运管平台.我想这样做的目的是: (1)半自动化或者全自动化安全运维规则,提高工作效率,降低人力成本. (2)现有安全厂商提高的产品无法满足用户日益增长业务安全需求,业务架构变更.

Spring MVC注解配置结合Hibernate的入门教程及其代码实例

原文:Spring MVC注解配置结合Hibernate的入门教程及其代码实例 源代码下载地址:http://www.zuidaima.com/share/1787210045197312.htm 1.概述 本文旨在搭建Spring MVC+Hibernate开发框架,通过一个简单的demo讲解Spring MVC的相关配置文件,以及通过注解方式实现简单功能. 开发框架:Spring+Spring MVC+Hibernate(Spring所用的版本为3.0.5). 数据库:MySQL(数据库名称

Spring第二天——IOC注解操作与AOP概念

大致内容 spring的bean管理(注解实现) AOP原理 log4j介绍 spring整合web项目的演示 一.spring注解实现bean管理 注解: 代码中一些特殊的标记,使用注解也可以完成一些相关的功能(写法"@") 方法上.类上(详见基础加强) 使用注解创建对象,注入属性(完成day01相似的功能) 可以使用注解,但不可能完全替代xml配置文件 准备工作: 导入包:除了day01的6个核心jar包(当然包括日志的包) 再加上aop的那个jar包(注解功能在里面),也就是图中

@ConfigurationProperties 注解使用姿势,这一篇就够了

前言 在编写项目代码时,我们要求更灵活的配置,更好的模块化整合.在 Spring Boot 项目中,为满足以上要求,我们将大量的参数配置在 application.properties 或 application.yml 文件中,通过 @ConfigurationProperties 注解,我们可以方便的获取这些参数值 使用 @ConfigurationProperties 配置模块 假设我们正在搭建一个发送邮件的模块.在本地测试,我们不想该模块真的发送邮件,所以我们需要一个参数来「开关」 di

spring mvc 编写处理带参数的Controller

在上一随笔记录的基础上,现记录编写处理带有参数的Controller. @Controller //这个注解会告知<context:component:scan> 将HomeController自动检测为一个Bean@RequestMapping("/home")  //这是根Urlpublic class HomeController {        private UserService userService;        @Autowired    public

如何用Spring将Service注入到Servlet中

解决方法有两种(推荐使用第二种) 方法一: 直接重写Servlet的Init()方法,代码如下: public void init(ServletConfig servletConfig) throws ServletException { ServletContext servletContext = servletConfig.getServletContext(); WebApplicationContext webApplicationContext = WebApplicationCo

applicationContext.xml和dispatcher-servlet.xml的区别

在SpringMVC项目中我们一般会引入applicationContext.xml和dispatcher-servlet.xml两个配置文件,这两个配置文件具体的区别是什么呢? Spring 官方文档介绍如下: Spring lets you define multiple contexts in a parent-child hierarchy. The applicationContext.xml defines the beans for the "root webapp context