Spring IOC - Bean的扫描

        @Component及其衍生注解:@Configuration、@Controller、@Service、@Repository标记的类,被Spring IOC扫描到后,即可被容器管理起来。其原理基本涵盖在AnnotationConfigApplicationContext构造函数体的三行代码里。

public AnnotationConfigApplicationContext(String... basePackages) {this();scan(basePackages);refresh();
}

1. this()

        这个无参构造方法做了三件事情:

  • 首先创建bean工厂,实际上是在父类GenericApplicationContext的构造器里完成的
public GenericApplicationContext() {this.beanFactory = new DefaultListableBeanFactory();
}
  • 然后初始化reader和scanner,这两个类就是AnnotationConfigApplicationContext类中的成员变量,作用是相同的,都是用来注册BeanDefinition对象,只不过场景不同
public AnnotationConfigApplicationContext() {
// 生成并注册5个BeanDefinition
// 1.ConfigurationClassPostProcessor
// 2.AutowiredAnnotationBeanPostProcessor
// 3.CommonAnnotationBeanPostProcessor
// 4.EventListenerMethodProcessor
// 5.DefaultEventListenerFactorythis.reader = new AnnotatedBeanDefinitionReader(this);
// spring提供api用来动态扫描注解
// 一般供扩展spring的时候用,内部扫描也是通过它this.scanner = new ClassPathBeanDefinitionScanner(this);
}

        AnnotatedBeanDefinitionReader用于解析单个类或一组类的注解,并将其转换为相应的BeanDefinition对象。它通常用于编程式地注册bean定义,即在代码中显式地调用AnnotatedBeanDefinitionReader的方法来注册bean定义。

        ClassPathBeanDefinitionScanner则用于在类路径下扫描指定的包,查找带有特定注解的类,并将其转换为相应的BeanDefinition对象。它通常用于自动化地注册bean定义,即在Spring容器启动时自动扫描指定包下的类,并将其转换为bean定义。

        总的来说,AnnotatedBeanDefinitionReader适用于手动注册bean定义,上述5个Spring提供的类就是通过reader编程试注入的,而ClassPathBeanDefinitionScanner适用于自动化注册bean定义。

        继续查看AnnotatedBeanDefinitionReader构造方法,上述5个类即通过AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)注册到beanDefinitionMap中

beanName

类名

是否BeanDefinitionRegistryPostProcessor

是否BeanFactoryPostProcessor

是否BeanPostProcessor

org.springframework.context.annotation.internalConfigurationAnnotationProcessor

ConfigurationClassPostProcessor

org.springframework.context.annotation.internalAutowiredAnnotationProcessor

AutowiredAnnotationBeanPostProcessor

org.springframework.context.annotation.internalCommonAnnotationProcessor

CommonAnnotationBeanPostProcessor

org.springframework.context.event.internalEventListenerProcessor

EventListenerMethodProcessor

org.springframework.context.event.internalEventListenerFactory

DefaultEventListenerFactory

2. scan(basePackages)

        在指定的基础包中执行扫描以查找组件类,这里是将扫描的类注册到beanDefinitionMap中。使用的正是上述创建scanner,该在创建的过程中,设置了一个@Component的注解类型过滤器,正是这个过滤器将扫描到的所有类过滤出标记了@Component及其衍生注解的类,逻辑如下:

//判断元信息读取器读取的类是否符合容器定义的注解过滤规则
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {// 如果读取的类的注解在排除注解过滤规则中,返回falsefor (TypeFilter tf : this.excludeFilters) {// 规则匹配功能if (tf.match(metadataReader, getMetadataReaderFactory())) {return false;}}// 如果读取的类的注解在包含的注解的过滤规则中,则返回true// 这里的includeFilters已经有了@Component过滤器for (TypeFilter tf : this.includeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return isConditionMatch(metadataReader);}}// 如果读取的类的注解既不在排除规则,也不在包含规则中,则返回falsereturn false;
}

3. refresh()

    该方法是Spring应用上下文的核心方法,它负责完成Spring容器的初始化和刷新工作,由于篇幅有限,这里主要讲解与扫描和解析相关的方法:invokeBeanFactoryPostProcessors(beanFactory)

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// getBeanFactoryPostProcessors()得到的是程序员通过API直接添加的BeanFactory// 这里getBeanFactoryPostProcessors()90%情况都是返回空// 只有10%情况不为空【程序员通过API手动添加】PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}
}

         接下来是invokeBeanFactoryPostProcessors方法了,该方法会调用在上述注入到beanDefinitionMap中的Spring内置的类BeanDefinitionRegistryPostProcessor及BeanFactoryPostProcessor对应的接口方法。整体逻辑可以分成两部分看:

  • 先调用BeanDefinitionRegistryPostProcessor的子类;
  • 再调用BeanFactoryPostProcessor的子类。

        这里面会调用一个关键类ConfigurationClassPostProcessor,他会解析@Configuration标记的类,及类中@Bean方法,涉及到full和lite模式,由于篇幅有限,将在下一篇讲解。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

6阶高清视频滤波驱动MS1681

MS1681 是一个单通道视频缓冲器,它内部集成6dB 增益的轨到轨输出驱动器和6 阶输出重建滤波器。MS1681 的-3dB 带宽为35MHz,压摆率为160V/us。MS1681 比无源LC 滤波器与外加驱动的解决方案能提供更好的图像质量。它单电源供电范围为2.5V 到5.5V&#xff0…

检验样本正态性

简介 在统计学中很多推论与正态分布有关,并且很多统计量构造为满足正态分布的形式,很多分布在特定条件近似于正态分布。因此,在统计推断中经常需要判断样本的正态性。本文介绍一些常用的方法。 环境和数据准备: import numpy a…

【Go】Go 语言教程--GO语言数组(十一)

往期回顾: Go 语言教程–介绍(一)Go 语言教程–语言结构(二)Go 语言教程–语言结构(三)Go 语言教程–数据类型(四)Go 语言教程–语言变量(五)Go …

Echarts使用,大数据量时,折线图曲线Y轴取值刻度不正确

如下图,当数据量过大时,会出现数值对应Y轴刻度显示不正确问题。 ​​​​​​​ 可检查配置项是否存在sampling字段 option {series: [{data: [...],type: line,smooth: true,symbolSize: 0,sampling: "average", // 注意此行}] }; samplin…

fpga下载程序到flash后无法在重新上电后自动加载程序

是器件的约束配置问题,这是正点原子artix7用的器件配置,如果不用就有问题 # 器件 set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] set_property CONFIG_MODE SPIx4 [current_design] set_property BITST…

WH5097D有源矩阵驱动的Mini LED背光应用方案

Miniled技术为lcd的全面升级版,Miniled的背光层在单位面积内可以容纳更多LED,从而大大提高背光源数量,因此可以进行区域亮度调节的设计,从而在个别区域实现关闭led从而达到完全的黑色,不仅减小了功耗,而且由…

Mac 和 Win,到底用哪个系统学编程?

今天来聊一个老生常谈的问题,学编程时到底选择什么操作系统?Mac、Windows,还是别的什么。。 作为一个每种操作系统都用过很多年的程序员,我会结合我自己的经历来给大家一些参考和建议。 接下来先分别聊聊每种操作系统的优点和不…

人体扫描新技术:手机扫描生成3D人体模型

人体扫描是一种新兴的技术,它可以通过数字化的方式,再现人体的内部结构。这种模型的应用范围广泛,不仅可以应用于医学领域,还可以用于虚拟现实、游戏开发等各个领域。通过人体扫描生成模型,我们可以实时地观察人体内部…

Trimble RealWorks处理点云数据(九)之点云分类后将地面导入Arcgis生成DEM

效果 步骤 1、las导入Trimble RealWorks 2、对点云数据预处理 可以参考这篇文章 TrimbleRealWorks点云数据预处理 我这边是把点云做了分类,而后将地面数据导出las 点云做为三维数据,后续步骤在arcscene中操作,能实时显示出来 3、arcscene创建las数据集

❤ Vue2+vue-cli+vue-router+vuex +elementUI/vant完整项目搭建 项目和配置(一)

Vue2vue-clivue-routervuex elementUI/vant项目搭建和配置webpack(一) 项目整套:Vue2vue-clivue-routervuex elementUI/vant 进一步配置完善已迁移到(二)部分 1、环境检测: node 环境 git --version git…

【youcans动手学模型】SENet 模型及 PyTorch 实现

欢迎关注『youcans动手学模型』系列 本专栏内容和资源同步到 GitHub/youcans 【youcans动手学模型】SENet 模型 【经典模型】SENet 模型-Cifar10图像分类1. SENet 卷积神经网络模型1.1 模型简介1.2 论文介绍1.3 分析与讨论 2. 在 PyTorch 中定义 SENet 模型类2.1 定义 SE Block…

【leetcode】61. 旋转链表 (python)

题目链接:61.旋转链表 写法一:暴力 class Solution(object):def rotateRight(self, head, k):""":type head: ListNode:type k: int:rtype: ListNode"""# 暴力:每次移动一个,时间复杂度 O(N^2)&am…