spring源码学习

news2024/12/24 8:29:20

1.xmlBeanFactory对defaultListableBeanFactory类进行扩展,主要用于从XML文档中获取BeanDefinition,对于注册及获取bean都是使用从父类DefaultListableBeanFactory继承的方法去实现。
xmlBeanFactory 主要是使用reader属性对资源文件进行读取和注册。
2.循环依赖。创建bean,核心方法
getBean → doGetBean → createBean → doCreateBean → createBeanInstance → populateBean
3.BeanDefinitionReader获取资源文件,封装成BeanDefinition,通过BeanDefinitionRegistry将其注册起来,保存到BeanDefinitionMap中。BeanFactory根据bean定义信息,通过反射实例化bean。
4.FactoryBean,灵活创建bean。调用getObject方法,才会生成bean,但没有严格的bean生命周期流程
5.spring中有两种bean:容器bean(比如BFPP)、自定义bean
6.FactoryBean和BeanFactory

  • FactoryBean本身也是一个bean对象,是一个小工厂,能够生产另外的Bean。“&”+ beanName就是FactoryBean对象。
  • BeanFactory是spring的根接口,是大工厂,生成各种各样的bean。普通bean对象没有"&"
    在这里插入图片描述

7.PostProcessor

  • 后置处理器、增强器。有了它,我们可以在各个过程中,合理应用它,对bean定义信息进行扩展、修改
  • 针对beanFactory的后置处理器
    • BeanFactoryPostProcessor
    • BeanDefinitionRegistryPostProcessor 继承 BeanFactoryPostProcessor
  • 针对bean的后置处理器
    • BeanPostProcessor
    • InstantiationAwareBeanPostProcessor 继承 BeanPostProcessor

8.循环依赖-三级缓存

  • 只用二级缓存会将AOP中创建代理对象的时机提前,设计之初是让bean在生命周期的最后一步完成代理而不是在实例化后就马上完成
  • 循环依赖发生时提前代理,没有循环依赖代理方式不变,依然是初始化后代理
  • 如果只有1个缓存,能解决循环依赖吗?
  • 如果只有2个缓存,能解决循环依赖吗?
    • 可以,但是有aop的话,会违反设计理念,提前创建代理对象
  • 为什么使用3级缓存之后,就可以解决带aop的循环引用
    • aop是在实例化后、属性赋值(被调用)时,判断是否需要生成代理对象的。但是我们没有办法知道对象什么时候要被调用,所以用第3级缓存,保存lambda表达式,当对象被调用时,执行lambda表达式,判断是否返回代理对象
  • 为什么spring不能解决构造方法的循环依赖
    • 在Bean调用构造器实例化之前,一二三级缓存并没有Bean的任何相关信息,在实例化之后才放入三级缓存中,因此当getBean的时候缓存并没有命中,这样就抛出了循环依赖的异常了。
  • 为什么多例Bean不能解决循环依赖?
    • 我们的bean是单例的,而且是字段注入(setter注入)的,单例意味着只需要创建一次对象,后面就可以从缓存中取出来,字段注入,意味着我们无需调用构造方法进行注入。
    • 如果是原型bean,那么就意味着每次都要去创建对象,无法利用缓存;
    • 如果是构造方法注入,那么就意味着需要调用构造方法注入,也无法利用缓存。
  • 三级缓存介绍
    • 一级缓存的作用:存放可用的成品bean;
    • 二级缓存的作用:为了将成熟Bean和纯净Bean分离(未注入属性),避免多线程下读取到不完整的Bean;存放半成品bean,半成品bean即已经调用完构造但是还没有注入属性和初始化;
    • 三级缓存的作用:用来生产半成品的bean,与getbean方法解耦,能解决aop增强下的循环依赖;存放函数接口/钩子函数,函数接口实现创建动态代理调用BeanPostProcessor,即其要加强的aop处理(为了避免重复创建,调用会返回动态代理对象或者原实例,再存储在二级缓存);

真正的解决循环依赖是靠二级缓存,不用三级缓存也可以解决循环依赖,但这样就造成了在实例化后就立马完成代理,违背了最后一步完成代理的原则;
在创建bean的时候,在哪里通过什么方式创建了动态代理:通过BeanPostProcessor创建动态代理,在初始化之后或在出现循环依赖时实例化之后(实例化 -> 属性注入 -> 初始化)
发生循环依赖会用到二级缓存,普通依赖过程只用到一三级缓存

9.配置类加@Configuration 和不加的区别
@Bean中被依赖的bean不会被重复加载
@Configuration为Full配置类,经过了enhance增强处理,所有@Bean方法会被BeanMethodInterceptor拦截,根据方法名获取单例,而不是重复加载

10.Spring是怎样避免读取到不完整的Bean

防止多线程下Spring读取到不完整Bean加了两把锁
一把锁放在getSingleton()方法三级缓存,第二个线程阻塞直到第一个线程把二三级缓存删除完;
一把锁放在getSingleton(,)方法,先从单例池再拿一遍单例对象(double check防重复创建单例bean)
怎么样可以在所有Bean创建完后做扩展代码?
ContextRefreshedEvent/SmartInitializingSingleton

11.接口

  • BeanFactory

  • Aware

  • BeanDefition

  • BeanDefitionRegistry

    • 注册bean定义信息,对bean定义信息进行增删改查
  • BeanDefitionReader

  • BeanFactoryProcessor

  • BeanPostProcessor

  • Environment

    • StandardEnviroment :当完成整个程序的加载之后,会运行很多系统的一些属性值,添加到当前对象。后续程序运行的时候,直接从当前对象获取,而不需要每次都去读取
      • System.getEnv()
      • System.getProperties()
  • FactoryBean

    BeanFactory和factoryBean的区别都是用来创建对象的。当使用BeanFactory时,必须要遵循完整的创建过程。这个过程由spring管理。factoryBean只需要调用getObject就可以返回具体对象,整个对象创建过程由用户自己控制,更加灵活

    • isSingleton
    • getObject :用来返回具体对象。可以new,也可以反射。核心的点在于进行容器获取对象时,每次创建对象之前,都会提前做当前对象的一个判断
    • getObjectType
    • getBean(“&” + beanName) 就是获取工厂
    • 意义在于,我需要的时候,通过当前工厂里的getObject方法创建,而不需要遵循bean的生命周期

12.spring执行流程

  • ClassPathXmlApplicationContext构造方法
    • 调用父类构造方法,进行相关对象创建,初始化操作,准备好一些需要的集合、对象
    • 设置配置文件路径
    • 调用AbstractApplicationContext#refresh 13个方法
      • prepareRefresh:准备刷新工作
        • 设置开启时间
        • 设置开闭状态
        • initPropertySource 初始化属性资源
        • getEnvironment 获取环境对象
          • 父类构造方法中调用了customizePropertySource——定制化属性资源
        • 创建监听器、需要发布的事件集合,方便做扩展属性
      • obtainFreshBeanFacotry获得一个刷新的bean容器,创建当前工厂对象 DefualtListableBeanFactory,同时加载配置文件到属性值到当前工厂中,最重要的就是beanDefinition
        • refreshBeanFactory:如果有bean工厂,关闭,销毁,产生新的工厂
          • createBeanFactory
            • new DefualtListableBeanFactory
          • customizeBeanFacotry:是否允许被覆盖、是否允许被重写
          • loadBeanDefinitions:因为配置文件是多个的,这个方法有N多个重载的方法。把当前这些配置文件解析,封装成Beandefinition
        • getBeanFactory
      • prepareBeanFactory:给当前bean工厂设置属性值,完成bean工厂的初始化工作
        • 加载beanFactoryPostProcessor
        • 忽略aware接口实现,后面是在invokeAwareMethod中实现的
      • postProcessorFactory:后置处理相关操作,方法是空的(模板方法)
      • invokeBeanFactoryPostProcessor,实例化并且执行所有已经注册的BFPP
      • 准备实例化、初始化所需要的一些类、对象。创建bean
  • 几个重要的实现类
    • HierarchicalBeanFactory 获取父类工厂。在doGetBean方法中需要获取父类工厂
    • ListableBeanFactory,枚举所有bean实例
    • ConfigurableBeanFactory
    • DefaultListableBeanFactory
  • RootBeanDefinition
  • GenericBeanDefinition
  • getMergedBeanDefinition方法
    在这里插入图片描述

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

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

相关文章

VMware ESXi 6.7 U3 Final - ESXi 6 系列最终版下载

VMware ESXi 6.7 U3 Final - ESXi 6 系列最终版下载 VMware ESXi 6 Standard 请访问原文链接:https://sysin.org/blog/vmware-esxi-6/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org VersionRelease NameRelease …

APIO2023 游记

GDOI 和 GDKOI 的游记都咕咕咕了,而且都炸了,APIO 的游记提前发,就是要破釜沉舟。 我是线上选手。 Day -7 我们原题检测,阿克了,毕竟是原题,虽然有两道博弈论黑题确实挺毒瘤的。 教练让我做 APIO2012 的…

centos8安装mysql8

本次介绍捆绑包rpm方式安装mysql 首先到mysql官网:MySQL 1.下载捆绑包 2.上传至服务器 3.解压 tar -xvf mysql捆绑包.tar 4.重点来了,按照以下顺序分别安装(命令中的版本号按照自己下载的版本调整) rpm -ivh mysql-community-common-8.0.26-1.el7.x86_64.rpm rpm -ivh my…

东南亚市场攻略:如何利用海外网红实现品牌曝光与销售增长

在当今数字化时代,社交媒体的兴起改变了品牌推广和市场开发的方式。尤其是在东南亚地区,网红营销迅速发展,成为品牌开发该地市场的重要策略之一。本文Nox聚星将和大家详细探讨出海品牌该如何利用海外网红营销来开发东南亚市场。 ​一、东南亚…

怎么做邮件营销?邮件营销必备攻略

电子邮件营销是与受众沟通、建立关系和推动转化有效的方式之一。然而,撰写有效的电子邮件营销活动需要创造力和方法技巧的结合。做好电子邮件营销能够为企业带来长期的客源,并为其培养稳定优质的客户,为企业带来长期收益。在这篇文章中&#…

这样做WhatsApp群组营销,转化率猛UP

WhatsApp群组营销是一种利用WhatsApp群组进行推广和营销活动的策略。通过创建或参与相关主题的群组,您可以与潜在客户建立联系,传递信息并促进销售。 以下是一些WhatsApp群组营销的建议: 1.确定目标受众,建立目标群组&#xff1a…

2023天一永安杯部分wp

web Query 布尔盲注 import requests import stringdictionary string.digitsstring.ascii_letters"_-{,}" url "http://cd5a2660b462c867.node.nsctf.cn/login.php" xxx"" for i in range(1,666):print("正在爆破第{}位".format…

关闭eslint - vue篇

文章目录 一、问题描述二、问题解决1、首先是比较旧的vue项目2、创建项目的时候,不要选eslint3、如果你使用的编辑软件是webstorm4、创建的项目没有webpack.base.conf.js文件,但是有 .eslintrc.js5、比较新的vue项目,目录没有(直接…

升级iOS16.5后无法使用闪电转USB3相机转换器怎么办?

上周,苹果给大家推送了iOS 16.5更新,号称修复了超14个漏洞。但很快,安装了更新的iPhone和iPad用户发现iOS 16.5的一个BUG,Lightning转USB 3相机转换器无法工作。 使用闪电转 USB 3 相机转换器,你可以轻松地将照片和视…

云时通供应链中台 | 打造供应链智慧大脑,实现70%订单交易自动化

在外部环境巨变的三年中,有些消费品制造和零售企业却仍然在自己的赛道逆势增长,这些企业无一例外先一步通过数字化武装自身,打造供应链护城河,为企业实现降本增效。 供应链和物流服务,是商业活动最底层的支撑系统之一…

Postman接口工具、中的全局/环境/集合变量的使用及优先级

变量的使用场景 Postman的变量主要用于参数化和关联 应用1: 常用变量可以按使用范围设置成集合或全局变量应用2: 一套接口要在不同的环境上测试时, 可以新建两个环境,比如test环境和stage环境, 两个环境中添加base_url变量并设置不同的值, 请求中接口的url中使用{{base_url}},…

DJ8-3 shell 进程监控(ps、sleep、kill)

目录 8.6 进程监控 8.6.1 获取进程状态信息:ps 命令 8.6.2 暂停进程运行:sleep 命令 8.6.3 终止进程运行:kill 命令 8.6 进程监控 8.6.1 获取进程状态信息:ps 命令 1、不带参数的 ps 不带参数的 ps 命令运行时&#…

自监督对比学习系列论文(二):有引导对比学习--SCCL,SwAV,PCL,SupervisedCon

自监督对比学习 本篇承接前一篇自监督对比学习的介绍自监督对比学习系列论文(一):无引导对比学习–MOCO,SimCLR,这次主要关注于包含先验指导的对比学习,这一指导更进一步的可以区分为聚类指导以及标签指导两种类型。前…

CMake 安装与打包

书接上回,前面我们已经介绍了动态库、静态库的构建和使用,这里将介绍项目构建完成后的安装和打包发布 上一节: 动态库、静态库的构建与使用_爱钓鱼的歪猴的博客-CSDN博客 目录 一、安装 1、理解install命令 2、CMakeLists.txt 3、执行安装…

Class 08 - 数据的读取和保存 R语言中的管道(pip)功能

Class 08 - 数据的读取和保存 & R语言中的管道(pip)功能 数据的读取和保存data() - 加载R中的数据集readr 功能包介绍readr 包中读取文件的函数read_csv() 读取 .csv 文件 readxl 包读取Excel文件read_excel() - 读取Excel文件excel_sheets() - 读取…

windows平台的视频播放软件-potplayer

可以播放多种格式的视频,可以将大视频按需裁剪为多个指定的小视频, 裁剪方式:快捷键altc打开如下界面 从上往下的功能大致描述为: 1、选择裁剪得到的视频的存储路径 2、设置才见得到的视频文件的前缀名 3、这个功能很重要&#xf…

ChatGPT帮你写简历找工作

随着随着毕业时间的到来,应届生将要面临求职问题,根据官方的统计,2023届高校毕业生预计达1158万人,就业市场竞争激烈,无论是校园招聘,招聘会,线上招聘除了自身的准备和个人能力,都会…

优秀的前端开发框架

优秀的前端开发框架 1.Vue Vue2文档:Vue.js Vue3文档:Vue.js - 渐进式 JavaScript 框架 | Vue.js 用于构建用户界面的渐进式框架 Vue的核心库只关注视图层。可与elementUI配合Element - The worlds most popular Vue UI framework 2.React 原先的Fa…

动态库、静态库的构建与使用

一、理解动态库与静态库 静态、动态是指链接 所谓静态、动态是指链接。回顾一下,将一个程序编译成可执行程序的步骤:链接: 把外部函数的代码(通常是后缀名为.lib和.a的文件),添加到可执行文件中。这就叫做…

Java面试知识点(全)-分布式和微服务-redis面试知识点

redis是什么 redis是一种支持Key-Value等多种数据结构的存储系统。可用于缓存、事件发布或订阅、高速队列等场景。该数据库使用ANSI C语言编写,支持网络,提供字符串、哈希、列表、队列、集合结构直接存取,基于内存,可持久化。 为…