spring源码学习

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方法
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Maven属性与版本管理

文章目录 1 属性1.1 问题分析1.2 解决步骤步骤1:父工程中定义属性步骤2:修改依赖的version 2 配置文件加载属性步骤1:父工程定义属性步骤2:jdbc.properties文件中引用属性步骤3:设置maven过滤文件范围步骤4:测试是否生效 3 版本管理 在这一章节内容中,我们将学习两个…

cpp11实现线程池(一)——项目介绍

项目介绍 线程池是库的形式提供给用户,是必须放到代码中,不能单独运行,亦称为基础组件 第一版线程池任务对象使用继承技术,提供一个抽象基类Task,里面有一个纯虚函数run(),使用时继承该类,并重…

c++综合学习

1.函数调用 传值调用:在函数内部修改形式参数,不改编实际参数的值;引用调用:即指针调用,传入的是变量的指针,则在函数内部修改形式参数,实际参数跟着改变。 2. 数组 数组名即该数组的首地址&a…

CSPM 未来发展的思考

由于数据泄露的持续威胁以及云的短暂和快节奏的特性,只有在最基础的层面上保护您的云才有意义。组织已经转向 CSPM 解决方案来锁定他们的平台。 今天我们来聊聊什么是CSPM,它如何去产生有有效的帮助,未来会向哪发展。 什么是 CSPM&#xff1…

阿拉德手游服务端Centos搭建教程

阿拉德手游服务端Centos搭建教程 大家好我是艾西,又有几天没有更新文章了。这几天看了看还是有不少人对手游感兴趣,今天给大家分享一款早些年大火的pc游戏,现在也有手游了“阿拉德”。 你是否还记得DNF,一天你不小心救了赛丽亚&a…

Win10系统电脑开机黑屏一直转圈无法进入桌面怎么办?

Win10系统电脑开机黑屏一直转圈无法进入桌面怎么办?有用户电脑开机了之后无法进入到桌面中,开机了之后,电脑桌面只有显示一个黑屏和转圈的图标,一直都无法进入到桌面中。强制重启电脑之后依然是这样,那么这个情况怎么去…

今天公司来了个拿 30K 出来的测试,算是见识到了基础的天花板

今天上班开早会就是新人见面仪式,听说来了个很厉害的大佬,年纪还不大,是上家公司离职过来的,薪资已经达到中高等水平,很多人都好奇不已,能拿到这个薪资应该人不简单,果然,自我介绍的…

Mysql-存储过程简单入门

定义: 存储过程的英文是 Stored Procedure 。它的思想很简单,就是一组经过 预先编译 的 SQL 语句 的封装。 执行过程:存储过程预先存储在 MySQL 服务器上,需要执行的时候,客户端只需要向服务器端发出调用 存储过程的命…

Godot引擎 4.0 文档 - 循序渐进教程 - 监听玩家输入

本文为Google Translate英译中结果,DrGraph在此基础上加了一些校正。英文原版页面: Listening to player input — Godot Engine (stable) documentation in English 监听玩家输入 在上一课创建您的第一个脚本的基础上,让我们看看任何游戏…

SpringBoot集成SpringSecurity从0到1搭建权限管理详细过程(认证+授权)

前言 最近工作需要给一个老系统搭建一套权限管理,选用的安全框架是SpringSecurity,基本上是结合业务从0到1搭建了一套权限管理,然后想着可以将一些核心逻辑抽取出来写一个权限通用Demo,特此记录下。 文章目录 前言1、SpringSecuri…

Elastic Stack

一、简介 ELK是一个免费开源的日志分析架构技术栈总称,官网https://www.elastic.co/cn。包含三大基础组件,分别是Elasticsearch、Logstash、Kibana。但实际上ELK不仅仅适用于日志分析,它还可以支持其它任何数据搜索、分析和收集的场景&#…

接口测试:Eolink Apikit 和 Postman 哪个更好用?

接口测试:Eolink Apikit 和 Postman 哪个更好用? 很多做服务端开发的同学,应该基本都用过 Postman 来测试接口,虽然 Postman 能支撑日常工作,但是总感觉还是少了点什么,比如需要 Swagger 来维护接口文档&am…

nginx压测记录

nginx压测记录 1 概述2 原理3 环境3.1 设备与部署3.2 nginx配置/服务器配置 4 netty服务5 步骤6 结果7 写在最后 1 概述 都说nginx的负载均衡能力很强,最近出于好奇对nginx的实际并发能力进行了简单的测试,主要测试了TCP/IP层的长链接负载均衡 2 原理 …

YOLOv5区域检测+声音警报

YOLOv5区域检测声音警报 1. 相关配置2. 检测区域设置3. 画检测区域线(不想显示也可以不画)4. 报警模块5. 代码修改5.1 主代码5.2 细节修改(可忽略) 6. 实验效果 本篇博文工程源码下载 链接1:https://github.com/up-up-…

远程桌面连接工具在哪里下载?

在市场上,有很多种不同的工具可用。一些远程桌面连接工具(如RayLink)具有高清流畅、操作简单和连接速度快的特点。而其他一些连接工具则更注重保护安全和数据保密性。不同的远程桌面连接工具各有特点,需要根据不同的需求进行选择。…

[AI图片生成]自己搭建StableDiffusion安装过程

前言 最近尝试玩玩AI图片生成,安装一路坑 出个一路安装成功的记录 开始 找个空间大的盘符,这玩意将来会很占空间.一个模型大约5g左右,你可能还会装很多模型创建个目录,路径不要有中文安装git 下载地址 详细教程 (如果有忽略)下载 Python3.10.0,记得勾选添加到环境变量选项,安…

ChatGPT帮你写简历找工作

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

2023 hnust 大三下 人工智能导论课程 期中考试复习笔记

前言 ★大概率考✦个人推测考点※补充内容没有完全覆盖“人工智能导论复习2023.pdf”的重点致谢:hwl、lyf、lqx 题型 问答:5*10分综合:15分设计:25分开放题/论述题:10分 第1章 绪论 人工智能的定义 智能 思考与…

Android平台外部编码数据(H264/H265/AAC/PCMA/PCMU)实时预览播放技术实现

开发背景 好多开发者可能疑惑,外部数据实时预览播放,到底有什么用? 是的,一般场景是用不到的,我们在开发这块前几年已经开发了非常稳定的RTMP、RTSP直播播放模块,不过也遇到这样的场景,部分设…

MySQL和Redis如何保证数据一致性?

前言 由于缓存的高并发和高性能已经在各种项目中被广泛使用,在读取缓存这方面基本都是一致的,大概都是按照下图的流程进行操作: 但是在更新缓存方面,是更新完数据库再更新缓存还是直接删除缓存呢?又或者是先删除缓存再…