SpringIOC之创建Bean的核心方法doGetBean

news2024/11/29 2:39:36

概述

面向资源(XML、Properties)面向注解定义的 Bean 是如何被解析成 BeanDefinition(Bean 的“前身”),并保存至 BeanDefinitionRegistry 注册中心里面,实际也是通过 ConcurrentHashMap 进行保存。

Spring 底层 IoC 容器 DefaultListableBeanFactory,实现了 BeanFactory 和 BeanDefinitionRegistry 接口,这个时候它处于“就绪状态”,当我们显示或者隐式地调用 getBean(...) 方法时,会触发加载 Bean 阶段,获取对应的 Bean。在该方法中,如果是单例模式会先从缓存中获取,已有则直接返回,没有则根据 BeanDefinition 开始创建这个 Bean。

主体流程:getBean doGetBean createBean doCreateBean createBeanInstance、instantiate、populateBean、initializeBean、registerDisposableBeanIfNecessary(注册销毁方法)

BeanFactory 体系结构

下来熟悉下Sprig容器BeanFactory的体系

  • org.springframework.beans.factory.BeanFactory,Spring IoC 容器最基础的接口,提供依赖查找单个 Bean 的功能

  • org.springframework.beans.factory.ListableBeanFactory,继承 BeanFactory 接口,提供依赖查找多个 Bean 的功能

  • org.springframework.beans.factory.HierarchicalBeanFactory,继承 BeanFactory 接口,提供获取父 BeanFactory 的功能,具有层次性

  • org.springframework.beans.factory.config.ConfigurableBeanFactory,继承 HierarchicalBeanFactory 接口,提供可操作内部相关组件的功能,具有可配置性

  • org.springframework.beans.factory.config.AutowireCapableBeanFactory,继承 BeanFactory 接口,提供可注入的功能,支持依赖注入

  • org.springframework.beans.factory.config.ConfigurableListableBeanFactory,继承上面所有接口,综合所有特性,还提供可提前初始化所有单例 Bean 的功能

org.springframework.beans.factory.support.DefaultListableBeanFactory,Spring 底层 IoC 容器,依赖注入的底层实现

getBean(String name) 方法,根据名称获取 Bean,当然还有许多重载方法

最终都会调用

doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) 方法

下面是编程方法获取Bean对象的方法

       // 创建 BeanFactory 容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        // XML 配置文件 ClassPath 路径
        String location = "classpath:dependency-lookup-context.xml";
        // 加载配置
        int beanDefinitionsCount = reader.loadBeanDefinitions(location);
        System.out.println("Bean 定义加载的数量:" + beanDefinitionsCount);
        // 依赖查找
        System.out.println(beanFactory.getBean("user","1","jack2"));

按照这个代码调试整理成下图的流程图

下图是关于doGetBean 方法这一层的执行逻辑。其他的核心方法后面在更新文章。

总结

  • 可以看到这个方法加载 Bean 的过程中,会先从缓存中获取单例模式的 Bean;

  • 不管是从缓存中获取的还是新创建的,都会进行处理,如果是 FactoryBean 类型则调用其 getObject() 获取目标对象;

  • BeanFactory 可能有父容器,如果当前容器找不到 BeanDefinition 则会尝试让父容器创建;

  • 创建 Bean 的任务交由 AbstractAutowireCapableBeanFactory 去完成;

  • 如果获取到的 Bean 不是我们想要类型,会通过类型转换机制转换成目标类型

获取 beanName

从缓存中获取单例 Bean

FactoryBean 的处理

非单例模式依赖检查

BeanFactory 层次性加载 Bean 策略

将 beanName 标记为已创建

获取 RootBeanDefinition

依赖 Bean 的处理

不同作用域的 Bean 的创建

单例模式

多例模式

其他模式

过程如下:

  1. 从当前容器获取该模式的 Scope 对象 scope,不存在则抛出异常

  1. scope 中获取 beanName 对应的对象(看你的具体实现),不存在则执行原型模式的四个步骤进行创建

想要自定义一个作用域,可以实现 org.springframework.beans.factory.config.Scope 接口,并往 Spring 应用上下文注册即可 这个也是一个拓展接口

类型转换

如果入参 requiredType 不为空,并且 Bean 不是该类型,则需要进行类型转换,过程如下:

  1. 通过类型转换机制,将 Bean 转换成 requiredType 类型,对 Spring 的类型转换机制参考 org.springframework.core.convert.support.DefaultConversionService

我们也可以基于此做拓展的。

  1. 转换后的 Bean 为空则抛出异常

  1. 返回类型转换后的 Bean 对象

归纳拓展

对 BeanFactory 接口的体系结构进行了分析,得知 DefaultListableBeanFactory 是 BeanFactory 的最底层实现,也就是 Spring 的底层 IoC 容器。接着分析了 AbstractBeanFactorygetBean(...) 方法,当我们显示或者隐式地调用这个方法时,会触发 Bean 的加载。上面对 Bean 的加载过程进行了分析。

不同作用域的 Bean 的创建,底层都会调用 AbstractAutowireCapableBeanFactorycreateBean(...)方法进行创建,创建 Bean 的过程涉及到 Bean 生命周期的大部分阶段,例如实例化阶段、属性赋值阶段、Aware 接口回调阶段、初始化阶段都是在这个方法中完成的。

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

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

相关文章

强缓存与协商缓存

Ⅰ、http缓存 HTTP 缓存策略 分为 > 「强制缓存」 和 「协商缓存」 为什么需要 HTTP 缓存 呢 ? &#x1f447; 直接使用缓存速度 >> 远比重新请求快 缓存对象有那些呢 &#xff1f;&#x1f447; 「图片」 「JS文件」 「CSS文件」 等等 文章目录Ⅰ、http缓存Ⅱ…

Hi3559av100平台8路1080P/720P输入配置流程梳理

平台&#xff1a; hi3559av100 硬件连接&#xff1a; 8路YUV422 -> 4路 2lane MIPI -> hi3559av100 最终效果&#xff1a; 经过处理后&#xff0c;后端可以实现8路独立视频流处理&#xff1b; 可以自由和后级VPSS/VENC/VO等模块进行绑定和处理 前言&#xff1a; &…

Spring-整合Mybatis

Spring-整合Mybatis 6&#xff0c;Spring整合 6.1 Spring整合Mybatis思路分析 6.1.1 环境准备 在准备环境的过程中&#xff0c;我们也来回顾下Mybatis开发的相关内容: 步骤1:准备数据库表 Mybatis是来操作数据库表&#xff0c;所以先创建一个数据库及表 create database…

IDEA设置默认JDK、Maven版本问题汇总

遇到的问题&#xff1a;使用IDEA导入一个Maven多模块项目遇到关于JDK和Maven版本相关的问题&#xff0c;这里记录一下解决办法。如何修改当前项目JDK和Maven的版本&#xff1f;修改当前项目对应Maven版本&#xff1a;File -> Setting -> 搜索Maven修改JDK版本&#xff0c…

图像处理--OpenCV学习笔记

内容简介 OpenCV是应用广泛的开源图像处理库&#xff0c;包括基本的图像处理方法&#xff1a;几何变换&#xff0c;形态学变换&#xff0c;图像平滑&#xff0c;直方图操作&#xff0c;模板匹配&#xff0c;霍夫变换&#xff1b;特征提取和描述方法&#xff1a;理解角点特征&a…

Linux驱动开发基础__工作队列

目录 1 引入 2 内核函数 2.1 定义work 2.2 使用 work&#xff1a;schedule_work 2.3 其他函数 3 代码 3.1 gpio_key_drv.c 3.2 button_test.c 4 内部机制 4.1 Linux 2.x 的工作队列创建过程 4.2 Linux 4.x 的工作队列创建过程 1 引入 前面讲的定时器、下半部 task…

ASEMI整流模块MDQ100-16的优点是什么?

编辑-Z ASEMI整流模块MDQ100-16参数&#xff1a; 型号&#xff1a;MDQ100-16 最大重复峰值反向电压&#xff08;VRRM&#xff09;&#xff1a;1600V 最大RMS电桥输入电压&#xff08;VRMS&#xff09;&#xff1a;1700V 最大平均正向整流输出电流&#xff08;IF&#xff0…

【内网安全】——Linux提权姿势

作者名&#xff1a;白昼安全主页面链接&#xff1a; 主页传送门创作初心&#xff1a; 一切为了她座右铭&#xff1a; 不要让时代的悲哀成为你的悲哀专研方向&#xff1a; web安全&#xff0c;后渗透技术每日emo&#xff1a; 希望你在新的一年也能更好&#xff0c;不惧流言蜚语&…

Django drf使用Django自带的用户系统的注册功能实现

在写登录功能的时候看着网上的视频学着做,然后看了源码的时候发现了一些有意思的功能,因此写这一篇笔记分享给大家. 1.阅读Django自带用户系统源码 1.1 阅读User类源码 系统自带的用户系统的models文件的位置\site-packages\django\contrib\auth\models.py,打开这个文件发现…

python爬虫--re模块简介

Python re正则表达式模块用法详解 前面章节介绍了一些系统自带的工具函数&#xff0c;如 id()、max()。这些函数在 Python 启动时会自动加载进来&#xff0c;不需要我们做任何事情。但并不是所有的模块都是自动加载进来的&#xff0c;因为有些模块不常用&#xff0c;它们只是在…

记录一次web server服务器编程过程中的bug

按照书上和视频中的代码比对没有问题&#xff0c;但是read函数输出不了连接的http请求&#xff0c;不断编译了好几遍还是不行&#xff0c;确定是端口的问题 首先&#xff0c;在云服务器中安全规则里已经允许了相应端口&#xff0c;如果还不可以&#xff0c;可以查看一下系统防火…

MyBatis 入门教程详解

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

配电室辅控项目无线组网远程在线控制系统解决方案

方案背景 配电室是电力系统末端配电网中传输、分配电能的主要电气设备场所&#xff0c;是城市配电网系统的重要组成部分&#xff0c;起到保护、计量、分配电能的作用。 长期以来&#xff0c;配电室管理工作一直是供电系统运行管理的薄弱环节之一。一些配电室开关跳闸、危险气…

【C++提高编程】set/ multiset 容器详解(附测试用例与结果图)

目录1 set/ multiset 容器1.1 set基本概念1.2 set构造和赋值1.3 set大小和交换1.4 set插入和删除1.5 set查找和统计1.6 set和multiset区别1.7 set容器排序1 set/ multiset 容器 1.1 set基本概念 简介&#xff1a; 所有元素都会在插入时自动被排序 本质&#xff1a; set/mu…

搜广推 召回层主流策略 (多路召回、Embedding召回)

😄 简单介绍下召回层的框架,不细致讨论。 文章目录 1、多路召回1.1 多路召回的策略1.2 多路召回的优点和缺点2、Embedding召回2.1、Embedding技术分类2.2、如和做Embedding召回Reference1、多路召回 1.1 多路召回的策略 所谓的“多路召回”策略,就是指采用不同的策略、特…

Linux编辑器vim

本文已收录至《Linux知识与编程》专栏&#xff01; 作者&#xff1a;ARMCSKGT 演示环境&#xff1a;CentOS 7 目录 前言 正文 vim常用方式 进入vim 退出vim vim基本模式及模式功能 命令模式 插入模式 底行模式 替换模式 视图模式 配置vim 自己配置vim 自动化配置…

选择排序基本概念

选择排序基本概念1.选择排序1.1 基本概念1.2 选择排序执行步骤有1.3 对于5个元素的值步骤次数1.4 选择排序大O记法表示2. 将[4,2,7,1,3]进行选择排序 【实战】2.1 第一次轮回步骤2.2 第二次轮回步骤2.3 第三次轮回步骤2.4 第四次轮回步骤3.选择排序代码实现3.1 根据最小值排序3…

TypeScript快速入门

TypeScript快速入门1.TypeScript介绍1.1.TypeScript为什么要为JS添加类型支持1.2.TypeScript相比JS优势2.TypeScript初体验2.1.安装编译TS的工具包2.2.编译并运行TS代码2.3.简化运行TS代码3.TypeScript常用类型3.1.类型注解3.2.常用基础类型3.3.原始类型 number/string/boolean…

前端基础html css js

html&#xff1a;框架 css&#xff1a;美化 jp&#xff1a;交互 HTML 1.基础标签 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>这是我的滴滴滴一个网页</title></head><body><h1>一号 标题&…

Pygame显示文字

使用Pygame显示文字的步骤如图1所示。图1 显示文字的步骤1 Pygame的初始化通过以下代码实现Pygame的初始化。import pygame pygame.init()其中&#xff0c;第1行代码的作用是在程序中导入pygame模块&#xff1b;第2行代码的作用是实现pygame的初始化。2 屏幕的创建使用如下代码…