spring - AnnotationConfigApplicationContext启动之reader、scanner、register逻辑整理

news2025/7/21 21:26:04

前言

我们在使用spring framework时一般都喜欢按照以下方式写启动

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

而我们的AnnotationConfigApplicationContext的内容如下

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {

// 构造DefaultListableBeanFactory、AnnotatedBeanDefinitionReader、ClassPathBeanDefinitionScanner

this();

register(componentClasses);

refresh();

}

其中的this()部分如下:

public AnnotationConfigApplicationContext() {

StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");

// 额外会创建StandardEnvironment

this.reader = new AnnotatedBeanDefinitionReader(this);

createAnnotatedBeanDefReader.end();

this.scanner = new ClassPathBeanDefinitionScanner(this);

}

其实主要是生成类的reader、scanner、生成AppConfig.class的beandefinition

以下是AnnotationConfigApplicationContext类的继承结构图

下面我们来整理一下AnnotationConfigApplicationContext启动除了除子refresh()以外内容

1.factory生成

beanfactory使用的是GenericApplicationContext的beanfactory,类是DefaultListableBeanFactory,其中instantiationStrategy用类文件读取方式是由系统环境参数org.graalvm.nativeimage.imagecode是否存在决定,如存在用SimpleInstantiationStrategy,不存在用CglibSubclassingInstantiationStrategy,他们两关系如下:

public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy

他们的差别就是一个java反射的原理生成instance,另外一个可以利cglib方式生成instance

另外还有DefaultResourceLoader中的classloader生成,主要是利用当前线程的 Thread.currentThread().getContextClassLoader()来生成

2.生成reader AnnotatedBeanDefinitionReader

1) 创建生成StandardEnvironment

2) 生成conditionEvaluator,主要是为了@Conditional,通过生成ConditionEvaluator对象,其中context属性主要是通过生成ConditionContextImpl对象,主对指定了beanfactory、environment、resourceloader、classloader,这里的resourceloader其实还是指定AnnotationConfigApplicationContext对象,因为他是实现了接口BeanDefinitionRegistry

this.resourceLoader = (resourceLoader != null ? resourceLoader : deduceResourceLoader(registry));

而这里的resourceLoader传进来的参数为空,所以需使用deduceResourceLoader方法,而这里的registry是AnnotationConfigApplicationContext对象

private ResourceLoader deduceResourceLoader(@Nullable BeanDefinitionRegistry source)

3) registerAnnotationConfigProcessors,主要为解析class生成object

    a. 首先设定beanfactory比较器

       beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE)

b. 然在在设定beanfactory的autowireCandidateResolver,主要用检查是否以autowired有关的内容

    beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver())

c. 向beanfactory中的 beanDefinitionMap中注册了如下类的BeanDefinition

ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor、EventListenerMethodProcessor、DefaultEventListenerFactory

2.生成scanner ClassPathBeanDefinitionScanner

1)向includeFilters里注册扫描注解

Component.class、javax.annotation.ManagedBean、javax.inject.Named

2)设定environment StandardEnvironment

3) 设定ResourceLoader

3.利用reader注册config类

1)生成启动configuration类的AnnotatedGenericBeanDefinition

a. 设定beanClass属性,主要利用传进来的class来设定

b. 设定metadata,主要是利用AnnotationMetadata.introspect(beanClass)返回StandardAnnotationMetadata对象

  • 设定introspectedClass属性
  • 设定mergedAnnotations属性,通过MergedAnnotations.from(introspectedClass,SearchStrategy.INHERITED_ANNOTATIONS, RepeatableContainers.none())
    • 通过isKnownEmpty检查类以下内容:
  1. 是否 满足条件(type.getName().startsWith("java.") || type == Ordered.class)
  2. .是否继承其他类
  3. .检查source.getDeclaredAnnotations内的method返回type满足(type == Class.class || type == Class[].class || type.isEnum())条件是否会抛异常
  • 返回生成TypeMappedAnnotations对象

2)判断以下条件是否需要跳过注册

      1. 1.检查1中的metadata是否正常生成
      2. 2.检查类不是Conditional.class
      3. 3.检查是否为接口
      4. 4.检查是否为component、conponentscan、import、importresource其中之一
      5. 5.检查是否有方法

满足1和2不检查3、4、5的条件

3)得到类的scope信息,scope信息中如有proxyMode并且设定,若没有scope相关信息设定默认值为singleton,proxymode为NO

4)生成beanname,如果class名前两位大写不变,否则会将第一位变成小写

5)在AnnotatedBeanDefinition中设定类中以下注解类的值

@Lazy、@Primary、@DependsOn、@Role、@Description

6)在beanfactory中生成最终中beandifinition,且如果scope信息中有proxy信息,会重新生成proxy的bendefinition按照bean名字替换原有的

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

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

相关文章

长时间预测模型DLiner、NLiner模型(论文解读)

前言 今年发布8月份发布的一篇有关长时间序列预测&#xff08;SOTA&#xff09;的文章&#xff0c;DLiner、NLine在常用9大数据集&#xff08;包括ETTh1、ETTh2、ETTm1、ETTm2、Traffic等&#xff09;上MSE最低&#xff0c;模型单变量、多变量实验数据&#xff1a; 在计算资…

Appium学习日记(二)—— 入门学习(安装Appium和配置环境)

入门 1、安装 Node.js 进入nodejs的官网下载安装包安装&#xff0c;一路点击下一步就行。 安装完毕之后&#xff0c;打开命令行&#xff0c;输入&#xff1a;node -v;显示类似于v10.13.0的版本号信息则表示安装成功。 2、安装Appium以及相关环境配置 Appium可以通过两种方式之…

【Kafka】(1)基础知识汇总

TOC &#xff08;1&#xff09;Kafka简介 &#xff08;1&#xff09;简单介绍 Kafka是一种消息队列&#xff0c;主要用来处理大量数据状态下的消息队列&#xff0c;一般用来做日志的处理。既然是消息队列&#xff0c;那么Kafka也就拥有消息队列的相应的特性了。 &#xff0…

Python3 VSCode 配置

VSCode&#xff08;全称&#xff1a;Visual Studio Code&#xff09;是一款由微软开发的跨平台免费源代码编辑器。VSCode 开发环境非常简单易用&#xff0c;仅需要安装相关的插件进行简易的配置就可以与原有的python环境组成一套具有简单的代码调试运行的开发工具。对于轻量级的…

聚焦“碳中和”,成都超算中心牵手重庆大学唱好“成渝双城记”

为了积极稳妥推进碳达峰碳中和&#xff0c;加快成渝双城经济圈建设。重庆大学牵手国家超算成都中心和成都计算狗数据科技有限公司&#xff0c;开展了关于CO2电催化还原反应的路径计算工作&#xff0c;积极推动川渝两地实现产学研合作和成果落地转化&#xff0c;深入推进能源革命…

【C++】运算符重载

前言&#xff1a;本教程使用到的工具是vs2010&#xff1b; 目录 为什么要重载运算符&#xff1f; 运算符重载 重载就一定要吗&#xff1f; 重载后的运算符和普通运算符有什么区别&#xff1f; 总结 为什么要重载运算符&#xff1f; 先看代码&#xff1a; #include <…

腾讯实时股票数据接口怎么获取行情?

腾讯实时股票数据接口怎么获取行情&#xff1f;以五粮液为例&#xff0c;要获取最新行情&#xff0c;访问数据接口&#xff1a; 返回数据&#xff1a;v_sz000858"51~五 粮 液~000858~27.78~27.60~27.70~417909~190109~227800~27.78~492~27.77~332~27.76~202~27.75~334~27.…

做SEO为什么有的网站收录很难做?

刚开始做网站的时候&#xff0c;经常遇到网站收录难的问题。有时候一个月都没收录&#xff0c;急得还是忍不住。我困惑了很久。每天都在想是什么原因导致我的网站没有被收录&#xff0c;很无奈也很难过。那时候我还不知道搜索引擎的工作原理&#xff0c;也不知道从何入手。我像…

为什么我抓不到baidu的数据包

最近&#xff0c;有位读者问起一个奇怪的事情&#xff0c;他说他想抓一个baidu.com的数据包&#xff0c;体验下看包的乐趣。 但却发现“抓不到”&#xff0c;这就有些奇怪了。 我来还原下他的操作步骤。 首先&#xff0c;通过ping命令&#xff0c;获得访问百度时会请求哪个I…

[TypeScript]Vue/React子组件实例暴露方法

最近几个月都在用TS开发各种项目&#xff0c;框架有涉及到Vue3,React18等&#xff1b; 记录一下Vue/React组件暴露出变量/函数的方法的写法&#xff1b; Vue2 回顾一下Vue2 组件暴露出去方法&#xff0c;它并没有约束&#xff0c;写在methods里的方法都能被调用&#xff0c;da…

UNIAPP实战项目笔记38 购物车的添加商品到购物车功能

UNIAPP实战项目笔记38 购物车的加入购物车功能 通过mapGetters实现此功能 在 shopcart.vue中 使用mapGetters中的 addShopCart方法实现商品数量的增加 核心代码 detail.vue <template><view class"details"><!-- 商品图 --><swiper :indicator…

如何在 JavaScript 中使用三元运算符

随着 React 的版本更新&#xff0c;内置 Hooks 越来越多了。很多 Hook 可能你压根都没听说过。但是 useEffect 这个老牌 Hook&#xff0c;相信每个用 React 的同学应该熟悉。 不优雅的 useEffect 不过对很多刚接触 React 的人来说&#xff0c;使用 useEffect 非常容易出现无限…

figma对比sketch有什么优势和不足?

设计行业的工具层出不穷。在我看来&#xff0c;sketch它在一定程度上被颠覆了PS&#xff0c;如今sketch已成为许多设计团队的设计工具。 那么Figma相对于Sketch有哪些优点&#xff1f;有哪些不便&#xff1f;让我们从几个方面来了解一下。 两款软件非常适合创建UI和组件库。Ske…

【LeetCode】数组系列-双指针

一、双指针算法基本介绍 算法思想&#xff1a;在遍历对象的过程中&#xff0c;不是普通的使用单个指针进行访问&#xff0c;而是使用两个相同方向&#xff08;快慢指针&#xff09;或者相反方向&#xff08;对撞指针&#xff09;的指针进行扫描&#xff0c;从而达到相应的目的…

现代 React Web 开发实战——kanban实现卡片拖拽

前提摘要&#xff1a; 学习宋一玮 React 新版本 函数组件 &Hooks 优先 开篇就是函数组件Hooks 实现的效果如下&#xff1a; 学到第11篇了 照葫芦画瓢&#xff0c;不过老师在讲解的过程中没有考虑拖拽目标项边界问题&#xff0c;我稍微处理了下这样就实现拖拽流畅了 下面就…

Flink基础原理

一、Flink的概述 我感觉就是一个实时的流处理程序,可以实时的从数据源读取数据,然后根据设置好的一系列算法, 对数据进行处理,最终输出到目的存储介质&#xff08;数据库、缓存等&#xff09;中去,和jdk1.8里面的数据流处理很像, 也有并行流、map、fifter等处理。二、Flink的基…

实验八 数据处理与多项式处理(matlab)

实验八 数据处理与多项式处理 1.1实验目的 1.2实验内容 1.3流程图 1.4程序清单 1.5运行结果及分析 1.6实验的收获与体会 1.1实验目的 1&#xff0c;掌握数据统计和分析的方法&#xff1b; 2&#xff0c;掌握数值插值与曲线拟合的方法&#xff1b; 3&#xff0…

如何使用 .Net Core 实现数据库迁移 (Database Migration)

当我们在编写基于数据库的应用程序时&#xff0c;随着需求的增加和改变&#xff0c;我们需要升级我们的数据库&#xff0c;变更数据库表的字段&#xff0c;当我们的系统的不同版本被部署到了不同的客户那里&#xff0c;在需要给客户升级时&#xff0c;我们如何实现数据库模式 (…

注解和反射

注解和反射注解元注解反射注解 注解和注释的区别 注解 annotation写在程序之中&#xff0c;程序可以识别&#xff0c;做出相应的动作处理&#xff0c;具有检查和约束程序的作用 注释 comment 写在程序之中&#xff0c;供人参考&#xff0c;提示使用&#xff0c;程序会自动忽…

云原生系统学习[Kubernetes]——02 Pod、Deployment、Service

云原生系统学习[Kubernetes]——02 Pod、Deployment、Service [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t9RomXCf-1668486830453)(./assets/image-20221103113345300.png)] 参考资料 什么是YAMLk8s官网文档k8s中文社区k8s-book 学多少&#…