手写spring简易版本,让你更好理解spring源码

首先我们要模拟spring,先搞配置文件,并配置bean

创建我们需要的类,beandefito,这个类是用来装解析后的bean,主要三个字段,id,class,scop,对应xml配置的属性

package org.zhw.ezspring.domain;
//解析后的bean
public class BeanDefinition {private String id;private String className;private String scope;public BeanDefinition(String id, String className, String scope) {this.id = id;this.className = className;this.scope = scope;}public BeanDefinition() {}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}public String getScope() {return scope;}public void setScope(String scope) {this.scope = scope;}
}

然后配置下我们要用的beandemo,这个后面我没用,但是懂的都懂,让大家更好理解下,xml中class,就是我们bean的路径,因为我们要用到反射。

package org.zhw.ezspring.domain;public class DemoBean {private String Name;private String age;public String getName() {return Name;}public void setName(String name) {Name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}public DemoBean() {}public DemoBean(String name, String age) {Name = name;this.age = age;}
}

对了,我们还要使用一个jar包,这个可以用来解析xml文件,非常好用

然后我们开始模拟手写简易版spring,由于我已经全部写完了,就先把核心代码写在下面。

以防大家看不清,我把文件目录展示下

package org.zhw.ezspring.factory;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.zhw.ezspring.domain.BeanDefinition;
import org.zhw.ezspring.domain.DemoBean;import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;public class BeanFactory {
//    用来装beandefiton 的map
static ConcurrentHashMap<String, BeanDefinition> beanDiMap = new ConcurrentHashMap<>();
//    用来装单例bean的map
static HashMap<String, DemoBean> objectObjectHashMap = new HashMap<>();
//     实例化的时候,就加载beanpublic  BeanFactory(){
//        解析xml配置文件this("E:\\ideaspace\\ez-spring\\src\\resouces\\application.xml");}public BeanFactory(String path) {SAXReader reader = new SAXReader();try {// 读取XML文件Document document = reader.read(new File(path));// 获取根元素Element rootElement = document.getRootElement();// 遍历元素List<Element> elements = rootElement.elements();for (Element element : elements) {BeanDefinition beanDefinition = new BeanDefinition();beanDefinition.setClassName(element.attributeValue("className"));beanDefinition.setId(element.attributeValue("id"));beanDefinition.setScope(element.attributeValue("scope"));String scope = element.attributeValue("scope");
//                默认为单例if(scope!=null&&!"".equals(scope)){beanDefinition.setScope("singleton");}System.out.println(beanDefinition);
//                放入beandefitionmapbeanDiMap.put(beanDefinition.getId(),beanDefinition);iniSingletonObjects();}} catch (DocumentException e) {e.printStackTrace();}}private void iniSingletonObjects() {
//        1.遍历map
//        2.判断是不是单例,是就放入它Iterator<Map.Entry<String, BeanDefinition>> iterator = beanDiMap.entrySet().iterator();while (iterator.hasNext()){Map.Entry<String, BeanDefinition> entry = iterator.next();BeanDefinition value = entry.getValue();String scope = value.getScope();String id = value.getId();if (scope.equals("singleton")){DemoBean demoBean = new DemoBean();demoBean.setName("z");objectObjectHashMap.put(id,demoBean);}}}public   Object getBean(String id ) throws DocumentException {
//根据id,作为key去beandifitionmap中遍历,判断是单例还是多例,是单例就去单例map中找,不是则直接反射。
//        BeanFactory beanFactory = new BeanFactory();BeanDefinition beanDefinition = beanDiMap.get(id);if (Objects.isNull(beanDefinition)){throw new RuntimeException("beanFactory is null");}if ("singleton".equals(beanDefinition.getScope())){BeanDefinition beanDefinition1 = beanDiMap.get(id);return beanDefinition1;}
//        如何是多例,则使用反射创建beantry {Class<?> aClass = Class.forName(beanDefinition.getClassName());DemoBean o = (DemoBean) aClass.newInstance();} catch (Exception e) {throw new RuntimeException("获取bean失败");}return null;}
// 通过class,来获取beanpublic  <T>T getBean(Class<T> classz){String name = classz.getName();Set<Map.Entry<String, BeanDefinition>> entries = beanDiMap.entrySet();Map.Entry<String, BeanDefinition> first = entries.stream().filter(x ->name.equals(x.getValue().getClassName())).findFirst().get();BeanDefinition value = first.getValue();if (value.getScope().equals("singleton")){return (T) beanDiMap.get(value.getId());}
//        不是单例就通过反射创建新的else {try {String id = value.getId();BeanDefinition beanDefinition = beanDiMap.get(id);Class<?> aClass = Class.forName(beanDefinition.getClassName());DemoBean o = (DemoBean) aClass.newInstance();} catch (Exception e) {throw new RuntimeException("获取bean失败");}}return null;}public static void main(String[] args) {BeanFactory beanFactory = new BeanFactory();try {Object demo1 = beanFactory.getBean("demo1");Object demo2 = beanFactory.getBean("demo1");System.out.println(demo1==demo2);} catch (Exception e) {throw new RuntimeException(e);}}}

这是我们的结果,免得说我失败了,两个单例bean的地址完全相同

ok,让我们开始解析我手写的代码,非常简单易懂,哈哈

首先我们需要new,两个map,一个用来装解析bean后的beandefitonmap,一个用来装单例bean,因为spring原理,bean单例,就是要从单例map里面找得嘛。

然后我们首先要解析xml,new个工厂,在new工厂的过程中,我们就要对bean进行解析,包装为beandefiton,放到beandefitonmap中去。同时要默认为单例bean,所以没有加scope的bean要写为单例bean。还要对beandefinitionmap进行遍历,把单例bean,放入单例beanmap中

为什么我们可以遍历xml,是因为我们用了dom4j,百度ai直接搜,dom4j解析xml,我直接粘贴复制过来的

一个有参,一个无参,这个应该看得懂撒。

       private void iniSingletonObjects() {
//        1.遍历map
//        2.判断是不是单例,是就放入它Iterator<Map.Entry<String, BeanDefinition>> iterator = beanDiMap.entrySet().iterator();while (iterator.hasNext()){Map.Entry<String, BeanDefinition> entry = iterator.next();BeanDefinition value = entry.getValue();String scope = value.getScope();String id = value.getId();if (scope.equals("singleton")){DemoBean demoBean = new DemoBean();demoBean.setName("z");objectObjectHashMap.put(id,demoBean);}}}
public  BeanFactory(){
//        解析xml配置文件this("E:\\ideaspace\\ez-spring\\src\\resouces\\application.xml");}public BeanFactory(String path) {SAXReader reader = new SAXReader();try {// 读取XML文件Document document = reader.read(new File(path));// 获取根元素Element rootElement = document.getRootElement();// 遍历元素List<Element> elements = rootElement.elements();for (Element element : elements) {BeanDefinition beanDefinition = new BeanDefinition();beanDefinition.setClassName(element.attributeValue("className"));beanDefinition.setId(element.attributeValue("id"));beanDefinition.setScope(element.attributeValue("scope"));String scope = element.attributeValue("scope");
//                默认为单例if(scope!=null&&!"".equals(scope)){beanDefinition.setScope("singleton");}System.out.println(beanDefinition);
//                放入beandefitionmapbeanDiMap.put(beanDefinition.getId(),beanDefinition);iniSingletonObjects();}} catch (DocumentException e) {e.printStackTrace();}}

然后我们就来写关于获取bean的方式,一个根据id获取,一个根据class获取。

根据id,先去beandefitonmap中去找,根据id,然后判断是不是空,还是单例bean,单例bean就去单例map中去找,多例则是用反射创建bean。

    public   Object getBean(String id ) throws DocumentException {
//根据id,作为key去beandifitionmap中遍历,判断是单例还是多例,是单例就去单例map中找,不是则直接反射。
//        BeanFactory beanFactory = new BeanFactory();BeanDefinition beanDefinition = beanDiMap.get(id);if (Objects.isNull(beanDefinition)){throw new RuntimeException("beanFactory is null");}if ("singleton".equals(beanDefinition.getScope())){BeanDefinition beanDefinition1 = beanDiMap.get(id);return beanDefinition1;}
//        如何是多例,则使用反射创建beantry {Class<?> aClass = Class.forName(beanDefinition.getClassName());DemoBean o = (DemoBean) aClass.newInstance();} catch (Exception e) {throw new RuntimeException("获取bean失败");}return null;}

根据class获取bean,先用class获取bean的名字,然后我们去beandefitonmap中去找bean,然后判断是不是单例bean,这里我脑子有点混乱了,从beandftionmap中已经获取了bean,然后还要去单例map中获取,这不是多此一举吗?如果不是,自己通过反射,new一个新的bean

关于我通过class,获取bean,我感觉我写的很混乱,写的不是很好,如果错了,不要怪我哈,以供借鉴提醒。

public  <T>T getBean(Class<T> classz){String name = classz.getName();Set<Map.Entry<String, BeanDefinition>> entries = beanDiMap.entrySet();Map.Entry<String, BeanDefinition> first = entries.stream().filter(x ->name.equals(x.getValue().getClassName())).findFirst().get();BeanDefinition value = first.getValue();if (value.getScope().equals("singleton")){return (T) beanDiMap.get(value.getId());}
//        不是单例就通过反射创建新的else {try {String id = value.getId();BeanDefinition beanDefinition = beanDiMap.get(id);Class<?> aClass = Class.forName(beanDefinition.getClassName());DemoBean o = (DemoBean) aClass.newInstance();} catch (Exception e) {throw new RuntimeException("获取bean失败");}}return null;}

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

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

相关文章

第二讲:NJ网络配置

Ethernet/IP网络拓扑结构 一. NJ EtherNet/IP 1、网络端口位置 NJ的CPU上面有两个RJ45的网络接口,其中一个是EtherNet/IP网络端口(另一个是EtherCAT的网络端口) 2、网络作用 如图所示,EtherNet/IP网络既可以做控制器与控制器之间的通信,也可以实现与上位机系统的对接通…

MySQL --- 表的操作

在对表进行操作时&#xff0c;需要先选定操作的表所在的数据库&#xff0c;即先执行 use 数据库名; 一、创建表 create table 表名( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎 ; 说明&#xff1a…

从零入门 AI for Science(AI+药物) #Datawhale AI 夏令营

使用平台 我的Notebook 魔搭社区 https://modelscope.cn/my/mynotebook/preset 主要操作 运行实例&#xff0c;如果有时长尽量选择方式二&#xff08;以下操作基于方式二的实例实现&#xff09; 创建文件夹&#xff0c;并重命名为 2.3siRNA 上传两个文件 到文件夹&#…

BGP路由反射器

原理概述 缺省情况下&#xff0c;路由器从它的一个 IBGP对等体那里接收到的路由条目不会被该路由器再传递给其他IBGP对等体&#xff0c;这个原则称为BGP水平分割原则&#xff0c;该原则的根本作用是防止 AS内部的BGP路由环路。因此&#xff0c;在AS内部&#xff0c;一般需要每台…

【Android】数据存储方案——文件存储、SharedPreferences、SQLite数据库用法总结

文章目录 文件存储存储到文件读取文件 SharedPreferences存储存储获取SharedPreferences对象Context 类的 getSharedPreferences() 方法Activity 类的 getPreferences() 方法PreferenceManager 类中的 getDefaultSharedPreferences() 方法 示例 读取记住密码的功能 SQLite数据库…

4.Java Web开发模式(javaBean+servlet+MVC)

Java Web开发模式 一、Java Web开发模式 1.javaBean简介 JavaBeans是Java中一种特殊的类&#xff0c;可以将多个对象封装到一个对象&#xff08;bean&#xff09;中。特点是可序列化&#xff0c;提供无参构造器&#xff0c;提供getter方法和setter方法访问对象的属性。名称中…

JAVA代码审计JAVA0基础学习(需要WEB基础知识)DAY2

JAVA 在 SQL执行当中 分为3种写法&#xff1a; JDBC注入分析 Mybatis注入分析 Hibernate注入分析 JDBC 模式不安全JAVA代码示例部分特征 定义了一个 sql 参数 直接让用户填入id的内容 一个最简单的SQL语句就被执行了 使用安全语句却并没有被执行 Mybatis&#xff1a; #…

【MetaGPT系列】【MetaGPT完全实践宝典——多智能体实践】

目录 前言一、智能体1-1、Agent概述1-2、Agent与ChatGPT的区别 二、多智能体框架MetaGPT2-1、安装&配置2-2、使用已有的Agent&#xff08;ProductManager&#xff09;2-3、多智能体系统介绍2-4、多智能体案例分析2-4-1、构建智能体团队2-4-2、动作/行为 定义2-4-3、角色/智…

【OpenCV C++20 学习笔记】调节图片对比度和亮度(像素变换)

调节图片对比度和亮度&#xff08;像素变换&#xff09; 原理像素变换亮度和对比度调整 代码实现更简便的方法结果展示 γ \gamma γ校正及其实操案例线性变换的缺点 γ \gamma γ校正低曝光图片矫正案例代码实现 原理 关于OpenCV的配置和基础用法&#xff0c;请参阅本专栏的其…

五、工厂方法模式

文章目录 1 基本介绍2 案例2.1 Drink 抽象类2.2 Tea 类2.3 Coffee 类2.4 DrinkFactory 抽象类2.5 TeaFactory 类2.6 CoffeeFactory 类2.7 Client 类2.8 Client 类运行结果2.9 总结 3 各角色之间的关系3.1 角色3.1.1 Product ( 抽象产品 )3.1.2 ConcreteProduct ( 具体产品 )3.1…

生物信息学新突破:在英特尔 Gaudi 2 上实现 ProtST 蛋白质语言模型加速

引言 随着人工智能技术的快速发展&#xff0c;蛋白质结构预测和语言模型在生物信息学领域扮演着越来越重要的角色。ProtST作为一种新兴的蛋白质语言模型&#xff0c;其性能在英特尔 Gaudi 2 加速器的助力下得到了显著提升。本文将探讨如何利用英特尔 Gaudi 2 加速 ProtST 模型…

哈希表相关的力扣题和讲解和Java、C++常用的数据结构(哈希法)

20240725 一、什么时候适用什么样的结构。1.java中1.1 HashSet&#xff1a;1.2 TreeSet&#xff1a;1.3 LinkedHashSet&#xff1a;1.4 HashMap&#xff1a;1.5 TreeMap&#xff1a;1.6 LinkedHashMap&#xff1a;1.7 总结 2. c中2.1 std::unordered_set&#xff1a;2.2 std::s…

项目实战——外挂开发(30小时精通C++和外挂实战)

项目实战——外挂开发&#xff08;30小时精通C和外挂实战&#xff09; 外挂开发1-监控游戏外挂开发2-秒杀僵尸外挂开发3-阳光地址分析外挂开发4-模拟阳光外挂开发5-无限阳光 外挂开发1-监控游戏 外挂的本质 有两种方式 1&#xff0c;修改内存中的数据 2&#xff0c;更改内存中…

谷粒商城实战笔记-54-商品服务-API-三级分类-拖拽效果

文章目录 一&#xff0c;54-商品服务-API-三级分类-修改-拖拽效果1&#xff0c;el-tree控件加上允许拖拽的属性2&#xff0c;是否允许拖拽3&#xff0c;完整代码 一&#xff0c;54-商品服务-API-三级分类-修改-拖拽效果 本节的主要内容是给三级分类树形结构加上拖拽功能&#…

Mysql 集群搭建 05

文章目录 1. Mysql主从复制集群搭建1.1 主库配置1.2 从库配置 2. 分库分表2.1 拆分策略2.2 实现技术2.2.1 MyCat概述2.2.2 MyCat入门2.2.3 配置 schema.xml 3. 双主双从4. 双主双从读写分离 1. Mysql主从复制集群搭建 主从复制是指将主数据库的 DDL 和 DML 操作通过二进制日志…

VMware Cloud Foundation ESXi 主机

一、准备嵌套 ESXi 主机环境# 1)物理 ESXi 主机信息 本次准备用于部署 VCF 嵌套实验环境的物理宿主机的配置信息如下图所示。其实,部署 VCF 环境主要对内存的大小要求比较高,部署完整的管理域相关组件下来差不多就要占用 200 GB左右内存,而对 CPU 和存储的需求可以根据实…

Pytorch使用教学8-张量的科学运算

在介绍完PyTorch中的广播运算后&#xff0c;继续为大家介绍PyTorch的内置数学运算&#xff1a; 首先对内置函数有一个功能印象&#xff0c;知道它的存在&#xff0c;使用时再查具体怎么用其次&#xff0c;我还会介绍PyTorch科学运算的注意事项与一些实用小技巧 1 基本数学运算…

idea中项目目录,文件显示不全问题

问题&#xff1a;idea中项目目录显示不全问题 解决办法1&#xff1a; 删除目录中的.idea文件 用idea重新打开文件就行了 办法2&#xff1a;手动导入为maven项目 1. 2. 3. 4.选择要导入的项目&#xff0c;导入为maven

在英特尔 Gaudi 2 上加速蛋白质语言模型 ProtST

引言 蛋白质语言模型 (Protein Language Models, PLM) 已成为蛋白质结构与功能预测及设计的有力工具。在 2023 年国际机器学习会议 (ICML) 上&#xff0c;MILA 和英特尔实验室联合发布了ProtST模型&#xff0c;该模型是个可基于文本提示设计蛋白质的多模态模型。此后&#xff0…

昇思25天学习打卡营第22天|Pix2Pix实现图像转换

Pix2Pix图像转换学习总结 概述 Pix2Pix是一种基于条件生成对抗网络&#xff08;cGAN&#xff09;的深度学习模型&#xff0c;旨在实现不同图像风格之间的转换&#xff0c;如从语义标签到真实图像、灰度图到彩色图、航拍图到地图等。这一模型由Phillip Isola等人在2017年提出&…