【Spring源码系列】Spring扫描-@ComponentScan底层原理解读

news2025/4/21 1:41:55

这里写目录标题

    • 前言
  • 一、@ComponentScan注解介绍
    • @ComponentScan作用
    • @ComponentScan重要参数
  • 二、@ComponentScan源码分析
    • 声明关键点
    • 源码解读
    • Spring扫描流程图

前言

先不废话了,直接干吧。

一、@ComponentScan注解介绍

@ComponentScan作用

@ComponentScan注解的作用可以简述为:将项目中所有被@Component注解标记的类---->组装成BeanDefinition---->然后以key value的形式注入到IOC容器中。

@ComponentScan重要参数

@ComponentScan中有多个参数,其中尤为重要的几个参数如下:

  1. value:用来指定basePackage的路径;
  2. excludeFilters:可以把被@Component标识的类排除注入到IOC容器;
  3. includeFilters:可以把不被@Component标识的类注入到IOC容器中;

示例:

@ComponentScan(value = "com.zhouyu",
		excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = UserService.class)},
		includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = User.class)})

二、@ComponentScan源码分析

声明关键点

在讲源码之前呢,我们可以先增强几个知识点的概念。这些知识点在阅读@ComponentScan注解源码中起着关键作用。

1、@ComponentScan只会扫描被 @Component标识的类。 诸如@Bean、spring.xml文件的< bean/>标签、编程式声明BeanDefinition等,都不会被@ComponentScan扫描;

2、@ComponentScan的excludeFiltersincludeFilters参数影响着类是否注入IOC容器。excludeFilters中指定了一个带有@Component注解的类,该类也不会注入到容器中;includeFilters中指定了一个不带有@Component注解的类,该类也会注入到容器中;

3、被@ComponentScan扫描注入到IOC容器中的BeanDefinition,其具体实现类是:ScannedGenericBeanDefinition

4、@ComponentScan扫描涉及到的相关注解:@Conditional@Scope@Lazy@Primary@DependsOn@Role@Description

  • @Conditional的作用是:即使该类被@Component修饰,但是Conditional返回false,该类也不会注入到IOC容器;
  • @Scope的作用是:仅仅作为一个标识,赋值给BeanDefinition的scope属性;
  • @Lazy、@Primary、@DependsOn、@Role:这几个类是一起被处理的,也只是用来给BeanDefinition赋值,分别对应着:setLazyInit(boolean)、setPrimary(boolean)、setDependsOn(value)、setRole(value)、setDescription(value);

5、须知Resource类和MetadataReader类。

  • Resource[]数组对象会存储basePackage包路径下所有的class文件(注意:是所有的class文件都会存储,无论有没有被@Component修饰);
  • MetadataReader类是Spring用来解析类的信息(比如类名、类中的方法、类上的注解,这些都可以称之为类的元数据)的一个工具类。MetadataReader、ClassMetadata、AnnotationMetadata都可以用来解析类信息;

6、@ComponentScan扫描最终生成两个map:Map<String, BeanDefinition> beanDefinitionMapMap<String, String> aliasMap

  • beanDefinitionMap用于存储BeanDefinition,key是beanName,value是BeanDefinition;
  • aliasMap用于存储bean的别名,key是别名,value是beanName。@Component没有设置bean别名功能,@Bean可以设置别名。
@ComponentScan("org.example")
public class AppConfig {

    /**
     * 声明:
     *  如果@Bean没有设置value参数,那么IOC中beanName = "createBookService";
     *  如果@Bean设置了多个value参数,那么IOC中beanName = array[0]
     */
    @Bean({"bookService","bookService2"})
    public BookService createBookService(){
        return new BookService();
    }
}	

源码解读

源码具体位置:org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
			Assert.notEmpty(basePackages, "At least one base package must be specified");
			Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
			// 遍历basePackages
			for (String basePackage : basePackages) {

				// 扫描basePackages下所有的文件,进行include、exclude、@Conditional判断后返回BeanDefinition
				Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

				for (BeanDefinition candidate : candidates) {
					ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); // scope解析:单例与多例
					candidate.setScope(scopeMetadata.getScopeName());

					String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); // 生成beanName:默认是类名首字母小写,如果@Component中指定了name则使用指定的name

					/* ScannedGenericBeanDefinition extends GenericBeanDefinition(AbstractBeanDefinition) implements AnnotatedBeanDefinition  */
					// 设置BeanDefinition的默认值
					if (candidate instanceof AbstractBeanDefinition) {
						postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
					}
					if (candidate instanceof AnnotatedBeanDefinition) {
						// 解析@Lazy、@Primary、@DependsOn、@Role、@Description
						AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
					}

					// 检查Spring容器中是否已经存在该beanName(如果存在则抛出异常)
					if (checkCandidate(beanName, candidate)) {
						BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
						definitionHolder =
								AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
						beanDefinitions.add(definitionHolder);

						// 注册: beanDefinitionMap.put(beanName, beanDefinition)
						registerBeanDefinition(definitionHolder, this.registry);
					}
				}
			}
			return beanDefinitions;
		}

Spring扫描流程图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/53482.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文搞懂PKI/CA

PKI1. 信息安全1. 1 主要攻击形式1.2 信息安全的目标2. PKI2.1 基本概念2.2 PKI的组成3. 数字证书3.1 基本概念3.2 证书的生成与验证3.3 证书链3.4 证书管理4. 时间戳服务1. 信息安全 随着数字经济、互联网金融、人工智能、大数据、云计算等新技术新应用快速发展&#xff0c;催…

GIS工具maptalks开发手册(二)02——渲染线

GIS工具maptalks开发手册(二)02——渲染线 效果 1、html版本 LineString.html <!DOCTYPE html> <html> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1"> <title>图形…

Redis 的 Java 客户端(Jedis、SpringDataRedis、SpringCache、Redisson)基本操作指南

Jedis 参考&#xff1a; Jedic 官方文档Jedis 托管在 github 上的源码 Redis 不仅是使用命令来操作&#xff0c;现在基本上主流的语言都有客户端支持&#xff0c;比如 java、C、C#、C、php、Node.js、Go 等。在官方网站里列一些 Java 的客户端&#xff0c;有 Jedis、Redisso…

CentOS 7 不显示ip

使用ip add或ifconfig插件看网络信息 进入文件夹/etc/sysconfig/network-scripts 修改对应的ens33网卡的配置文件&#xff0c;默认请工况下CentOS 7不启动网卡&#xff08;ONBOOTno&#xff09; 修改vim ifcfg-ens33中的ONBOOTno为ONBOOTyes 重启服务&#xff1a;service netwo…

【蓝桥杯省赛真题14】python围圈报数 青少年组蓝桥杯python编程省赛真题解析

目录 python围圈报数 一、题目要求 1、编程实现 2、输入输出 3、评分标准

2023年,想要靠做软件测试获得高薪,还有机会吗?

时间过得很快&#xff0c;一眨眼&#xff0c;马上就要进入2023年了&#xff0c;到了年底&#xff0c;最近后台不免又出现了经常被同学问道这几个问题&#xff1a;2023年还能转行软件测试吗&#xff1f;零基础转行可行吗&#xff1f; 本期小编就“2023年&#xff0c;入行软件测…

centernet的数据增强操作--仿射变换

centernet论文与代码剖析_无左无右的博客-CSDN博客_centernet原论文blogfirst_rank_ecpm_v1~rank_v31_ecpm-3-110164808-null-null.nonecase&utm_termcenternet&spm1018.2226.3001.4450 其实在这里也分析过。奈何当初写的代码不知道哪里去了&#xff1b; 本文原地址&am…

Java学习之方法重写/覆盖

目录 一、方法重写的概念 二、入门案例 三、使用细节 第一条 第二条 第三条 一、方法重写的概念 方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法 注释&#xff1a;包括直接继承和简介继承&…

连接阿里云MaxCompute数据源报错504 Gateway Time-out

背景 经济下行的大环境下&#xff0c;很多公司都在做出海业务&#xff0c;即把海外人民做为服务对象。我司亦不例外。最近在全职负责的一款数据产品&#xff0c;也需要在菲律宾&#xff08;马尼拉&#xff09;也部署一个站点。 站点部署成功&#xff0c;看起来一切顺利。既然…

k8s网络插件之Calico

Calico简介 Calico官方文档&#xff1a;https://projectcalico.docs.tigera.io/getting-started/kubernetes/quickstart Calico是一套开源的网络和网络安全解决方案&#xff0c;用于容器、虚拟机、宿主机之前的网络连接&#xff0c;它是一个纯三层的虚拟化网络解决方案&#…

Springboot毕业设计毕设作品,心理评测系统设计与实现

功能清单 【后台功能】 系统设置&#xff1a;设置关于我们、联系我们、加入我们、法律声明 广告管理&#xff1a;设置小程序首页轮播图广告和链接 留言列表&#xff1a;所有用户留言信息列表&#xff0c;支持删除 会员列表&#xff1a;查看所有注册会员信息&#xff0c;支持删…

QT笔记——vs中的qt项目 可调试源码

环境&#xff1a;vs2019 qt 5.12.2 1&#xff1a;首先我们需要选择我们的源码路径 右键解决方案-》属性-》通用属性-》调试源文件-》在窗口内添加QT下载时的源码**.src文件夹** 2.下载对应QT版本的PDB文件 http://download.qt.io/online/qtsdkrepository/windows_x86/desktop/…

PG第十一章-基准测试与 pgbench

性能基准线称为基准测试 一&#xff1a;关于基准测试 影响的关键因素有&#xff1a; 硬件&#xff0c;如服务器配置、 CPU 内存、存储&#xff0c;通常硬件越高级&#xff0c;系统的性能越好&#xff1b;网络&#xff0c;带宽不足也会严重限制系统整体性能表现&#xff1b;负…

双十二购买护眼台灯亮度多少合适?灯光亮度多少对眼睛比较好呢

现在越来越多的孩子近视情况严重&#xff0c;走在大街上&#xff0c;普遍都能见到大多数孩子都戴着眼镜&#xff0c;这不仅与我们的生活习惯、饮食健康有关&#xff0c;也受照明环境的影响&#xff0c;所以很多家长为了孩子的视力健康&#xff0c;开始使用护眼台灯来照明了。 …

短信服务调研

调研新技术方案的一般步骤&#xff1a; 列出所有竞品&#xff0c;根据品牌、功能、价格&#xff0c;选择最合适的一个购买或试用服务查阅相关文档和配置要单独写一个demo&#xff0c;体验一下 竞品有&#xff1a;七牛云、阿里云、网易云、腾讯云 本次选择为腾讯云&#xff1a…

springboot简述

文章目录一、SpringBoot简介1、springboot快速入门1、开发步骤1.创建springboot入门项目2.创建controller3.启动服务器4.测试2、对比spring3、springboot工程快速启动4.切换web服务器二、配置文件1.配置文件格式2.properties配置文件3.yaml格式配置文件1.语法规则2.yaml配置文件…

【C++天梯计划】1.10 二叉树(binary tree)

文章目录什么是二叉树&#xff1f;二叉树的定义二叉树的基本形态二叉树的性质例题1&#xff1a;二叉树的遍历题目描述输入输出样例代码例题2&#xff1a;哈夫曼树题目描述输入输出样例代码&#x1f386;&#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f389;&…

学成在线页面设计案例

html结构 <!DOCTYPE html> <html lang"zh"> <head> <meta charset"UTF-8"> <meta http-equiv"X-UA-Compatible" content"IEedge"> <meta name"viewport" content"widthdevice-width…

沉睡者IT - Web3采用现状:哪些企业采用了Web3,效果如何?

欢迎关注沉睡者IT&#xff0c;点上面关注我 ↑ ↑ 作为 Web 3 世界的“原住民”&#xff0c;我们已经能够看到个人和企业越来越多地尝试 Web 3 机制&#xff0c;推出 NFT、加密资产和数字商品。 了解他们为什么这样做、他们追求什么目标、哪些机制的效果最好和最差对我们来说…

python主题建模可视化LDA和T-SNE交互式可视化

我尝试使用Latent Dirichlet分配LDA来提取一些主题。 最近我们被客户要求撰写关于主题建模的研究报告&#xff0c;包括一些图形和统计输出。 本教程以自然语言处理流程为特色&#xff0c;从原始数据开始&#xff0c;准备&#xff0c;建模&#xff0c;可视化论文。 我们将涉及…