前言

开个新坑,来整点儿大项目。有这个想法是因为用了那么久的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);}
}

这个类的内容就比刚才的要复杂一些了,首先有这么两个方法:getBeanregisterBeanDefinition。而且,内部维护了一个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容器相关推荐

  1. 王式安概率论与数理统计基础课手写笔记-第一章概率与事件-第二章随机变量及其分布

    写在前面:做题还是要做的,但是课本上基础理论不能忘,比如每章前言,告知本章研究的内容及研究的方法.走过的路都算数. 文章目录 第一章 概率与事件 第二章 随机变量及其分布 第一章 概率与事件 第二章 ...

  2. 手把手教你手写Spring框架

    手写spring准备工作: 新建一个maven工程: 架构 新建类: package com.spring;public class keweiqinApplicationContext {priva ...

  3. 从头开始实现一个小型spring框架——手写Spring之集成Tomcat服务器

    手写Spring之集成Tomcat与Servlet 写在前面 一.Web服务模型及servlet 1.1 Web服务器 1.2 请求流程 二.实现 三.小结 写在前面 最近学习了一下spring的相关 ...

  4. 手写一个简单的IOC容器

    手写一个简单的IOC容器 原文 http://localhost:4000/2020/02/25/SSM/spring/%E6%89%8B%E5%86%99%E4%B8%80%E4%B8%AA%E5% ...

  5. JAVA项目代码手写吗_一个老程序员是如何手写Spring MVC的

    见人爱的Spring已然不仅仅只是一个框架了.如今,Spring已然成为了一个生态.但深入了解Spring的却寥寥无几.这里,我带大家一起来看看,我是如何手写Spring的.我将结合对Spring十多 ...

  6. 手写简版spring --1--创建简单的Bean容器

    一.声明 这个系列是我自己的学习笔记,为了在学习的过程中巩固知识而记录的,好强迫自己用心拜读,而不是进收藏夹.本系列都是基于小缚哥的文章和代码的,想要深入了解,请移步小缚哥博客 二.spring-Be ...

  7. 手写Spring DI依赖注入,嘿,你的益达!

    手写DI 提前实例化单例Bean DI分析 DI的实现 构造参数依赖 一:定义分析 二:定义一个类BeanReference 三:BeanDefinition接口及其实现类 四:DefaultBean ...

  8. 手写Spring-第二章-实现 Bean 的定义、注册、获取

    前言 上一章我们实现了一个简化的Bean容器,那么这一章开始,我们就要上一些强度了.这一章主要的目的是,让Spring容器来自动化实现Bean的创建,并且实现单例Bean的复用.在上一章,我们只实现了 ...

  9. python数据挖掘入门与实践-第一章-用最简单OneR算法对Iris植物分类

    前言: 这本书其实有配套代码的来着,但是有点坑的是,里面的代码对应的版本是有点旧的,用的时候会警告或者已经报错.甚至有些代码书里提了但是却没有写进去,要自己去摸索.我是每一章都跟着代码示例,把每一个步 ...

最新文章

  1. C2371 “imaxdiv_t”: 重定义;“_abs64”: 重定义;不同的链接
  2. Android两个tab吸顶,Android scrollView和viewpager嵌套 指示器吸顶 根据viewpager每
  3. 保守官僚 诺基亚就这样迷失在智能机时代?
  4. 进阶10 补充知识点
  5. 电脑老是自动重启怎么回事??
  6. 对‘cv::imread(cv::String const, int)’未定义的引用
  7. 使用非参数统计检验进行分析的指南
  8. 无线通信算法工程师知识地图
  9. 2021-06-16 srm平台电子化采购的优势
  10. 【最后一天报名】数据科学峰会分论坛:供应链、用户增长、电商零售
  11. vn.py2-行情记录的使用
  12. 技术经理成长复盘-聊聊核心骨干
  13. 7.0.高等数学四-隐函数存在定理
  14. 地球重力——黄金维教授,台湾交通大学
  15. R语言[]和[[]]操作的区别
  16. Python中int32转int64
  17. 使用 dlopen 和 dlsym 来使用 C++ 中的函数、类
  18. 【SuperMap-Leaflet】等值线/面裁剪参数设置
  19. Spark学习之路 (三)Spark之RDD
  20. JQuery点名表案例

热门文章

  1. ZED stereo camera开发入门教程(1)
  2. 2021年山东省职业院校技能大赛高职组“信息安全管理与评估”赛项规程
  3. 服务治理在猫眼娱乐的演进之路
  4. 360快视频回应侵权B站;朱啸虎猛批ICO;加拿大用Model X当警车丨价值早报
  5. 上海迪士尼度假区和斯凯奇达成数年战略联盟
  6. 初探MITM-中间人攻击
  7. 织梦主动提交_织梦CMS发表文章自动实现百度链接主动推送教程
  8. pycinrad学习入门笔记,数据为雷达新旧格式基数据、pup产品数据
  9. haimeiktv服务器系统,海媚 Haimei KBFG-9001 音效处理器
  10. 用DIV+CSS制作四川成都美食网页介绍