当前位置: 首页 > news >正文

手写Spring:第2章-创建简单的Bean容器

文章目录

  • 一、目标:创建简单的Bean容器
  • 二、设计:创建简单的Bean容器
  • 三、实现:创建简单的Bean容器
    • 3.0 引入依赖
    • 3.1 工程结构
    • 3.2 创建简单Bean容器类图
    • 3.3 Bean定义
    • 3.4 Bean工厂
  • 四、测试:创建简单的Bean容器
    • 4.1 用户Bean对象
    • 4.2 单元测试
  • 五、总结:创建简单的Bean容器

一、目标:创建简单的Bean容器

💡 Spring Bean 容器是什么?

  • Spring 包含并管理应用对象的配置和生命周期,在这个意义上它是一种用于承载对象的容器
    • 你可以配置你的每个 Bean 对象是如何被创建的。
    • 这些 Bean 可以创建一个单独的实例或者每次需要时都生成一个新的实例,以及它们是如何相互关联构建和使用的。
  • 如果一个 Bean 对象交给 Spring 容器管理,那么这个 Bean 对象就应该以类似零件的方式被拆解后存放到 Bean 的定义中。
    • 这样相当于一种把对象解耦的操作,可以由 Spring 更加容易的管理,就像处理循环依赖等操作。
  • 当一个 Bean 对象被定义存放以后,再由 Spring 统一进行装配,这个过程包括:Bean 的初始化、属性填充等。
    • 最终我们就可以完整的使用一个 Bean 实例化后的对象了。
  • 目标:定义一个简单的 Spring 容器,用于定义、存放和获取 Bean 对象。

二、设计:创建简单的Bean容器

💡 简单的 Spring Bean 容器如何实现?

  • 凡是可以存放数据的具体数据结构实现,都可以称之为容器
    • 例如:ArrayListLinkedListHashSet 等。
    • 但在 Spring Bean 容器的场景下,我们需要一种可以用于存放和名称索引式的数据结构,HashMap 是最合适的。
  • HashMap:是一种基于扰动函数、负载因子、红黑树转换等技术内容,形成的拉链寻址的数据结构。
    • 它能让数据更加散列的分布在哈希桶以及碰撞时形成的链表和红黑树上。
    • 它的数据结构会尽可能最大限度的让整个数据读取的复杂度在 O(1)~O(Logn)~O(n) 之间。
    • 当日在极端情况下也会有 O(n) 链表查找数据较多的情况,不过我们经过10万数据的扰动函数再寻址验证测试,数据会均匀的散列在各个哈希桶索引上。
    • 所以 HashMap 非常适合用在 Spring Bean 的容器实现上。
  • 一个简单的 Spring Bean 容器实现,还需 Bean 的定义、注册、获取三个基本步骤。

在这里插入图片描述

  • 定义BeanDefinition,它会包括 singleton、prototype、BeanClassName 等。目前初步实现一个 Object 类型用于存放对象。
  • 注册:这个过程就相当于我们把数据存放到 HashMap 中,只不过现在 HashMap 存放的是定义了的 Bean 对象信息。
  • 获取:最后就是获取对象,Bean 的名字就是 keySpring 容器初始化好 Bean 以后,就可以直接获取了。

三、实现:创建简单的Bean容器

3.0 引入依赖

pom.xml

<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency>
</dependencies>

3.1 工程结构

spring-step-01
|-src|-main|	|-java|		|-com.lino.springframework|			|-BeanDefinition.java|			|-BeanFactory.java|-test|-java|-com.lino.springframework.test|-bean|	|-UserService.java|-ApiTest.java

3.2 创建简单Bean容器类图

在这里插入图片描述

  • Spring Bean 容器的整个实现内容非常简单,也仅仅是包括了一个简单的 BeanFactoryBeanDefinition
    • 这里的类名称是与 Spring 源码中一致,只不过现在的类实现会相对来说更简化一些,在后续的实现再继续添加内容。
    • BeanFactory:用于定义 Bean 实例化信息,现在的实现是一个 Object 存放对象。
    • BeanDefinition:代表了 Bean 对象的工厂,可以存放 Bean 定义到 Map 中以及获取。

3.3 Bean定义

BeanDefinition.java

package com.lino.springframework;/*** @description: Bean 对象信息定义*/
public class BeanDefinition {/*** bean对象*/private Object bean;public BeanDefinition(Object bean) {this.bean = bean;}public Object getBean() {return bean;}
}
  • 目前的 Bean 定义中,只有一个 Object 用于存放 Bean 对象。
  • 在后续的实现中会逐步完善 BeanDefinition 相关属性的填充。
    • 例如:SCOPE_SINGLETON、SCOPE_PROTOTYPE、ROLE_APPLICATION、ROLE_SUPPORT、ROLE_INFRASTRUCTURE 以及 Bean Class 信息。

3.4 Bean工厂

BeanFactory.java

package com.lino.springframework;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @description: 简单的 Bean 工厂*/
public class BeanFactory {/*** bean对象Map*/private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();public Object getBean(String name) {return beanDefinitionMap.get(name).getBean();}public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {beanDefinitionMap.put(name, beanDefinition);}
}
  • Bean 工厂的实现中,包括了 Bean 的注册,这里注册的是 Bean 的定义信息。同时在这个类中还包括了获取 Bean 的操作。
  • 目前的 BeanFactory 仍然是简化的实现,但这种简化的实现内容也是整个 Spring 容器中关于 Bean 使用的最终体现结果。
    • 只不过实现过程只展示出基本的核心原理。

四、测试:创建简单的Bean容器

4.1 用户Bean对象

UserService.java

package com.lino.springframework.test.bean;/*** @description: 模拟用户 Bean 对象*/
public class UserService {/*** 查询用户信息*/public void queryUserInfo() {System.out.println("查询用户信息");}
}
  • 定义一个 UserService 对象。

4.2 单元测试

ApiTest.java

package com.lino.springframework.test;import com.lino.springframework.BeanDefinition;
import com.lino.springframework.BeanFactory;
import com.lino.springframework.test.bean.UserService;
import org.junit.Test;/*** @description: 测试类*/
public class ApiTest {@Testpublic void test_BeanFactory() {// 1.初始化 BeanFactoryBeanFactory beanFactory = new BeanFactory();// 2.注入beanBeanDefinition beanDefinition = new BeanDefinition(new UserService());beanFactory.registerBeanDefinition("userService", beanDefinition);// 3.获取beanUserService userService = (UserService) beanFactory.getBean("userService");userService.queryUserInfo();}
}
  • 在单元测试中主要包括 初始化 Bean 工厂、注册 Bean、获取 Bean 三个步骤。
  • Bean 的注册中,这里是直接把 UserService 实例化后作为入参传递给 BeanDefinition 的,在后续的陆续实现中,这部分会放入 Bean 工厂中实现。

测试结果

查询用户信息
  • 通过测试结果看是正常通过的。

五、总结:创建简单的Bean容器

  • 整篇关于 Spring Bean 容器的一个雏形就已经实现完成了。
  • 相对于一个知识的学习来说,写代码只是最后的步骤,往往整个思路、设计、方案,才更重要,只要你知道了因为什么,所以什么,才能让你有一个真正的理解。

相关文章:

手写Spring:第2章-创建简单的Bean容器

文章目录 一、目标&#xff1a;创建简单的Bean容器二、设计&#xff1a;创建简单的Bean容器三、实现&#xff1a;创建简单的Bean容器3.0 引入依赖3.1 工程结构3.2 创建简单Bean容器类图3.3 Bean定义3.4 Bean工厂 四、测试&#xff1a;创建简单的Bean容器4.1 用户Bean对象4.2 单…...

在Windows上通过SSH公私钥实现无密码登录Linux

在Windows上通过SSH公私钥实现无密码登录Linux 在Windows上生成SSH密钥对&#xff1a; 打开命令提示符或PowerShell窗口。 输入以下命令生成SSH密钥对&#xff1a; ssh-keygen -t rsa -b 4096按照提示输入密钥的保存路径和密码&#xff08;可选&#xff09;。 在指定的路径下…...

使用ppt和texlive生成eps图片(高清、可插入latex论文)

一、说明 写论文经常需要生成高清的图片插入到论文中&#xff0c;本文以ppt画图生成高质量的eps图片的实现来介绍具体操作方法。关于为什么要生成eps图片&#xff0c;一个是期刊要求&#xff08;也有不要求的&#xff09;&#xff0c;另一个是显示图像的质量高。 转化获得eps…...

html5学习笔记19-SSE服务器发送事件(Server-Sent Events)

https://www.runoob.com/html/html5-serversentevents.html 允许网页获得来自服务器的更新。类似设置回调函数。 if(typeof(EventSource)!"undefined"){var sourcenew EventSource("demo_sse.php");source.onmessagefunction(event){document.getElement…...

高效数据湖构建与数据仓库融合:大规模数据架构最佳实践

文章目录 数据湖和数据仓库&#xff1a;两大不同理念数据湖数据仓库 数据湖与数据仓库的融合统一数据目录数据清洗和转换数据安全和权限控制数据分析和可视化 数据湖与数据仓库融合的优势未来趋势云原生数据湖自动化数据处理边缘计算与数据湖融合 结论 &#x1f389;欢迎来到云…...

Java学习笔记——35多线程02

线程同步 线程同步卖票案例同步代码块同步方法块 线程安全的类StringBufferVectorHashtable Lock锁 线程同步 卖票案例 public class SellTicket implements Runnable{private int tickets10;Overridepublic void run(){while (true){if(tickets>0){System.out.println(Th…...

每日刷题-3

目录 一、选择题 二、编程题 1、计算糖果 2、进制转换 一、选择题 1、 解析&#xff1a;在C语言中&#xff0c;以0开头的整数常量是八进制的&#xff0c;而不是十进制的。所以&#xff0c;0123的八进制表示相当于83的十进制表示&#xff0c;而123的十进制表示不变。printf函数…...

储能直流侧计量表DJSF1352

安科瑞 华楠 具有CE/UL/CPA/TUV认证 DJSF1352-RN导轨式直流电能表带有双路直流输入&#xff0c;主要针对电信基站、直流充电桩、太阳能光伏等应用场合而设计&#xff0c;该系列仪表可测量直流系统中的电压、电流、功率以及正反向电能等。在实际使用现场&#xff0c;即可计量总…...

机器学习报错合集(持续更新)

文章目录 1 列表转numpy&#xff0c;尺寸不均匀问题 1 列表转numpy&#xff0c;尺寸不均匀问题 ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (4,) inhomogeneous pa…...

【android12-linux-5.1】【ST芯片】【RK3588】【LSM6DSR】驱动移植

一、环境介绍 RK3588主板搭载Android12操作系统,内核是Linux5.10,使用ST的六轴传感器LSM6DSR芯片。 二、芯片介绍 LSM6DSR是一款加速度和角速度(陀螺仪)六轴传感器,还内置了一个温度传感器。该芯片可以选择I2C,SPI通讯,还有可编程终端,可以后置摄像头等设备,功能是很…...

day-41 代码随想录算法训练营(19)动态规划 part 03

343.整数拆分 思路&#xff1a; 1.dp存储的是第i个数&#xff0c;拆分之后最大乘积2.dp[i]max(dp[i],max(j*(i-j),j*dp[i-j]));3.初始化&#xff1a;dp[0]dp[1]0,dp[2]1;4.遍历顺序&#xff1a;外层循环 3-n&#xff0c;内层循环 1-i 2.涉及两次取max&#xff1a; dp[i] 表…...

K8S安装部署 初始化操作(一)

准备好服务器和服务器资源 ip hostnameip资源 &#xff08;2核2G也可以&#xff09;k8s-master 192.168.37.1184核 4G 40G硬盘k8s-node1192.168.37.1192核 2G 20G硬盘k8s-node2192.168.37.1202核 2G 20G硬盘 初始操作三台同时执行 1、关闭防火墙 [rootlocalhost ~]# s…...

【多线程案例】单例模式(懒汉模式和饿汉模式)

文章目录 1. 什么是单例模式&#xff1f;2. 立即加载/“饿汉模式”3. 延时加载/“懒汉模式”3.1 第一版3.2 第二版3.3 第三版3.4 第四版 1. 什么是单例模式&#xff1f; 提起单例模式&#xff0c;就必须介绍设计模式&#xff0c;而设计模式就是在软件设计中&#xff0c;针对特殊…...

Anaconda - 操作系统安装程序 简要介绍

Anaconda 简要介绍 1. Anaconda 简介2. Anaconda 体系结构3. Anaconda 开发模型4. Anaconda 启动概述5. Anaconda 源码1. 接口2. 自定义组件3. 硬盘分区&#xff1a;使用python-blivet包4. Bootloader5. 各个步骤的配置&#xff1a;6. 安装软件包&#xff1a;7. 安装控制&#…...

【数据库设计】向量搜索HNSW算法优化

做向量存储的过程中&#xff0c;遇到向量搜索的情况处理&#xff0c;HNSW算法是目前向量搜索的主要算法之一&#xff0c;采用的是图算法&#xff0c;主要的问题是使用内存大&#xff0c;训练时间长。做算法优化过程中获得部分技巧&#xff0c;分享出来。 一、算法本身的优化 对…...

多通道振弦数据记录仪应用桥梁安全监测的关键要点

多通道振弦数据记录仪应用桥梁安全监测的关键要点 随着近年来桥梁建设和维护的不断推进&#xff0c;桥梁安全监测越来越成为公共关注的焦点。多通道振弦数据记录仪因其高效、准确的数据采集和处理能力&#xff0c;已经成为桥梁安全监测中不可或缺的设备。本文将从以下几个方面…...

深入了解HTTP代理的工作原理

HTTP代理是一种常见的网络代理方式&#xff0c;它可以帮助用户隐藏自己的IP地址&#xff0c;保护个人隐私和安全。了解HTTP代理的工作原理对于使用HTTP代理的用户来说非常重要。本文将深入介绍HTTP代理的工作原理。 代理服务器的作用 HTTP代理的工作原理基于代理服务器的作用。…...

2023年高教社杯数学建模国赛选题人数+C题进阶版修改思路详解

C题思路 修改版 C题保奖 数据预处理 3σ原则 区间判断法、人为判定 问题 1 聚类分析进行简单的分类 相互关系 数据服从正态分布&#xff08;K-S检验等判定分布类型后&#xff09; 才能做person相关性 图表结合&#xff08;热力图、数据结果表&#xff09; 分布规律 宏…...

第三章微服务配置中心

文章目录 Nacos配置中心统一配置管理在nacos中添加配置文件从微服务拉取配置 配置热更新多环境共享配置 搭建Nacos集群搭建集群初始化数据库配置Nacos启动nginx反向代理 Nacos配置中心 Nacos配置管理 Nacos除了可以做注册中心&#xff0c;同样可以做配置管理来使用。 统一配置…...

箭头函数(arrow function)与普通函数之间的区别是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 语法简洁性&#xff1a;⭐ this 的绑定&#xff1a;⭐ 不能用作构造函数&#xff1a;⭐ 没有 arguments 对象&#xff1a;⭐ 不适用于方法&#xff1a;⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

加密通信 + 行为分析:运营商行业安全防御体系重构

在数字经济蓬勃发展的时代&#xff0c;运营商作为信息通信网络的核心枢纽&#xff0c;承载着海量用户数据与关键业务传输&#xff0c;其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级&#xff0c;传统安全防护体系逐渐暴露出局限性&a…...

C++中vector类型的介绍和使用

文章目录 一、vector 类型的简介1.1 基本介绍1.2 常见用法示例1.3 常见成员函数简表 二、vector 数据的插入2.1 push_back() —— 在尾部插入一个元素2.2 emplace_back() —— 在尾部“就地”构造对象2.3 insert() —— 在任意位置插入一个或多个元素2.4 emplace() —— 在任意…...

【题解-洛谷】P10480 可达性统计

题目&#xff1a;P10480 可达性统计 题目描述 给定一张 N N N 个点 M M M 条边的有向无环图&#xff0c;分别统计从每个点出发能够到达的点的数量。 输入格式 第一行两个整数 N , M N,M N,M&#xff0c;接下来 M M M 行每行两个整数 x , y x,y x,y&#xff0c;表示从 …...