手写Spring-第一章-实现一个简单的Bean容器
前言
开个新坑,来整点儿大项目。有这个想法是因为用了那么久的Spring,但是某一天突然冒出来一个念头:Spring到底是怎么实现这些功能的。发现脑子一片空白。在我抽出纸巾擦干脑门儿上的汗之后,我决定去网上搜索Spring源码解读。但是找来找去,要么讲的乱七八糟,要么就是过于庞大,一下子堆到面前,看不下去。终于,找到了一个还不错的教程,作者基于Spring框架,自己手写了一个简化版的Spring,而且代码的命名、类之间的关系,都是根据真正的Spring来的,只不过有所简化。我想,这就是我要找的教程了。所以我也跟着一边学习,一边在这里记录自己的学习理解,也算是有所沉淀。
在这里说一下原作者的博客地址:https://bugstack.cn
作者叫小傅哥,教程的名字叫《手撸Spring》,也算个版权声明以及宣传吧~
教程的一开始,还是非常简单的。这也是吸引我学习下去的原因,由浅入深,逐步深入,才是正确的学习路线。在这一章,我们要搭建起一个简单的Bean容器,实现Bean的注册和获取。
工程结构
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─akitsuki
│ │ │ └─springframework
│ │ │ BeanDefinition.java
│ │ │ BeanFactory.java
│ │ │
│ │ └─resources
│ └─test
│ └─java
│ └─com
│ └─akitsuki
│ └─springframework
│ └─test
│ │ ApiTest.java
│ │
│ └─bean
│ UserService.java
看这里的工程目录,好像只有两个类。没错,我们一开始要做的就是这么多,两个类,就可以实现一个简单的Bean容器。
Bean定义
首先是我们两个类中的第一个类:BeanDefinition。
package com.akitsuki.springframework;/*** @author ziling.wang@hand-china.com* @date 2022/11/7 9:28*/
public class BeanDefinition {private Object bean;public BeanDefinition(Object bean) {this.bean = bean;}public Object getBean() {return bean;}
}
这里可能会觉得这个BeanDefinition有些莫名其妙,里面只有一个Object类型的属性bean。顾名思义,这里应该是用来放置我们实例化好的bean的。但实际上,这里是因为过于简化的结果。在后面的学习中,我们会逐渐扩充BeanDefinition的内容,比如加入bean的class、bean的属性和值等等内容。同时也会将现在的实例化bean进行移除。
所以BeanDefinition到底是用来做什么的呢,我理解,这个类是用来包装bean的一些“参数”的。bean的class是什么,有哪些属性,属性的初始化值是哪些,有没有初始化方法、销毁方法之类。就像它的名字一样,bean的定义,这个bean应该是什么样子的,由这个类来规定。
Bean工厂
看到这个名字,大家肯定都很清楚了,生产bean的工厂,还用到了工厂模式。
package com.akitsuki.springframework;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @author ziling.wang@hand-china.com* @date 2022/11/7 9:30*/
public class BeanFactory {private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();public Object getBean(String beanName) {return beanDefinitionMap.get(beanName).getBean();}public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {beanDefinitionMap.put(name, beanDefinition);}
}
这个类的内容就比刚才的要复杂一些了,首先有这么两个方法:getBean
和 registerBeanDefinition
。而且,内部维护了一个Map,用来存放bean定义。
既然是Bean的工厂,那么自然是要用来生产bean了。这里有个很有意思的地方,就是内部维护的map,不是存放bean的,而是存放bean定义的。从这里我们也可以看出,bean定义是我们实例化bean的一个模子的概念。我们先要把bean定义好,才能去实现它。
首先我们看 getBean
方法,这个方法是用来获取bean的。方法的内容则是从map中通过bean的名称,来获取相应的bean定义。这里是用bean的名称作为map的key来与bean定义进行关联。一开始我是有一些疑惑的,为什么bean的名称不是bean定义中的一个属性。但后来我考虑,bean定义中的内容,都是模板的内容,只有最终实例化好了的bean,才能有一个名称来与之对应,一个模板可以生产多个产品,也就是bean,所以bean的名称不能作为bean定义中的一个属性
然后我们看 registerBeanDefinition
。这个方法是用来注册bean定义的。我们要先把一个bean定义注册到Spring中,才能根据这个定义来实例化具体的bean。这个注册具体的体现方式,自然就是我们的各种bean配置文件以及注解了。当然我们现在还没有发展到那一步,在后面会去继续完善的。
测试!
首先,我们要有一个等待交给Spring管理的bean
package com.akitsuki.springframework.test.bean;/*** @author ziling.wang@hand-china.com* @date 2022/11/7 9:36*/
public class UserService {public void queryUserInfo() {System.out.println("查询用户信息");}
}
非常简单,但它确实可以作为一个bean,而且有一个方法可以对外提供服务,嗯,你已经是一个合格的bean了。
然后,我们就要来编写具体的测试方法了
package com.akitsuki.springframework.test;import com.akitsuki.springframework.BeanDefinition;
import com.akitsuki.springframework.BeanFactory;
import com.akitsuki.springframework.test.bean.UserService;
import org.junit.Test;/*** @author ziling.wang@hand-china.com* @date 2022/11/7 9:37*/
public class ApiTest {@Testpublic void testBeanFactory() {//初始化BeanFactoryBeanFactory beanFactory = new BeanFactory();//注册BeanBeanDefinition beanDefinition = new BeanDefinition(new UserService());beanFactory.registerBeanDefinition("userService", beanDefinition);//获取BeanUserService userService = (UserService) beanFactory.getBean("userService");userService.queryUserInfo();}
}
可以看到,这里我们先初始化了BeanFactory,然后新建了一个bean定义,并将其注册到了factory中。最后再由factory生产出这个bean。
可以看到,这时候我们的Spring已经初具雏形了,虽然是各方面都经过简化的结果,但我们已经完成了bean的注册、生产、获取等操作。在后面,我们会逐步完善,把这些操作变成自动化、读取配置文件来进行,让我们的小demo逐渐的更加接近真正的Spring。
相关源码可以参考我的gitee:https://gitee.com/akitsuki-kouzou/mini-spring
,这里对应的代码是mini-spring-01
手写Spring-第一章-实现一个简单的Bean容器相关推荐
- 王式安概率论与数理统计基础课手写笔记-第一章概率与事件-第二章随机变量及其分布
写在前面:做题还是要做的,但是课本上基础理论不能忘,比如每章前言,告知本章研究的内容及研究的方法.走过的路都算数. 文章目录 第一章 概率与事件 第二章 随机变量及其分布 第一章 概率与事件 第二章 ...
- 手把手教你手写Spring框架
手写spring准备工作: 新建一个maven工程: 架构 新建类: package com.spring;public class keweiqinApplicationContext {priva ...
- 从头开始实现一个小型spring框架——手写Spring之集成Tomcat服务器
手写Spring之集成Tomcat与Servlet 写在前面 一.Web服务模型及servlet 1.1 Web服务器 1.2 请求流程 二.实现 三.小结 写在前面 最近学习了一下spring的相关 ...
- 手写一个简单的IOC容器
手写一个简单的IOC容器 原文 http://localhost:4000/2020/02/25/SSM/spring/%E6%89%8B%E5%86%99%E4%B8%80%E4%B8%AA%E5% ...
- JAVA项目代码手写吗_一个老程序员是如何手写Spring MVC的
见人爱的Spring已然不仅仅只是一个框架了.如今,Spring已然成为了一个生态.但深入了解Spring的却寥寥无几.这里,我带大家一起来看看,我是如何手写Spring的.我将结合对Spring十多 ...
- 手写简版spring --1--创建简单的Bean容器
一.声明 这个系列是我自己的学习笔记,为了在学习的过程中巩固知识而记录的,好强迫自己用心拜读,而不是进收藏夹.本系列都是基于小缚哥的文章和代码的,想要深入了解,请移步小缚哥博客 二.spring-Be ...
- 手写Spring DI依赖注入,嘿,你的益达!
手写DI 提前实例化单例Bean DI分析 DI的实现 构造参数依赖 一:定义分析 二:定义一个类BeanReference 三:BeanDefinition接口及其实现类 四:DefaultBean ...
- 手写Spring-第二章-实现 Bean 的定义、注册、获取
前言 上一章我们实现了一个简化的Bean容器,那么这一章开始,我们就要上一些强度了.这一章主要的目的是,让Spring容器来自动化实现Bean的创建,并且实现单例Bean的复用.在上一章,我们只实现了 ...
- python数据挖掘入门与实践-第一章-用最简单OneR算法对Iris植物分类
前言: 这本书其实有配套代码的来着,但是有点坑的是,里面的代码对应的版本是有点旧的,用的时候会警告或者已经报错.甚至有些代码书里提了但是却没有写进去,要自己去摸索.我是每一章都跟着代码示例,把每一个步 ...
最新文章
- C2371	“imaxdiv_t”: 重定义;“_abs64”: 重定义;不同的链接
- Android两个tab吸顶,Android scrollView和viewpager嵌套 指示器吸顶 根据viewpager每
- 保守官僚 诺基亚就这样迷失在智能机时代?
- 进阶10 补充知识点
- 电脑老是自动重启怎么回事??
- 对‘cv::imread(cv::String const, int)’未定义的引用
- 使用非参数统计检验进行分析的指南
- 无线通信算法工程师知识地图
- 2021-06-16 srm平台电子化采购的优势
- 【最后一天报名】数据科学峰会分论坛:供应链、用户增长、电商零售
- vn.py2-行情记录的使用
- 技术经理成长复盘-聊聊核心骨干
- 7.0.高等数学四-隐函数存在定理
- 地球重力——黄金维教授,台湾交通大学
- R语言[]和[[]]操作的区别
- Python中int32转int64
- 使用 dlopen 和 dlsym 来使用 C++ 中的函数、类
- 【SuperMap-Leaflet】等值线/面裁剪参数设置
- Spark学习之路 (三)Spark之RDD
- JQuery点名表案例
热门文章
- ZED stereo camera开发入门教程(1)
- 2021年山东省职业院校技能大赛高职组“信息安全管理与评估”赛项规程
- 服务治理在猫眼娱乐的演进之路
- 360快视频回应侵权B站;朱啸虎猛批ICO;加拿大用Model X当警车丨价值早报
- 上海迪士尼度假区和斯凯奇达成数年战略联盟
- 初探MITM-中间人攻击
- 织梦主动提交_织梦CMS发表文章自动实现百度链接主动推送教程
- pycinrad学习入门笔记,数据为雷达新旧格式基数据、pup产品数据
- haimeiktv服务器系统,海媚 Haimei KBFG-9001 音效处理器
- 用DIV+CSS制作四川成都美食网页介绍