前言

开个新坑,来整点儿大项目。有这个想法是因为用了那么久的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. idea怎么调成黑色页面
  2. linux一键优化脚本1.0
  3. activePerl的PPM如何使用http代理
  4. 自己抽取的柱状图MpAndroidChart
  5. linux之找出两个文件里面相同的数据
  6. 通过VirtualQuery获取当前模块的句柄
  7. linux my.cnf基本参数,Linux中MySQL配置文件my.cnf参数说明
  8. 由m种数字组成的n位数有多少个
  9. 爬虫学习round02
  10. 解放双手,基于github travis-ci docker自动化部署java项目
  11. Solr -- 实时搜索
  12. java类Writer和类Reader小结
  13. bcb quickrep保存为 图片_干货|SCI论文中图片与组图技巧
  14. JESD204B 协议解析和参数理解
  15. RNA剪接体 Spliceosome | 冷冻电镜 | 结构生物学
  16. 怎么把m4a文件变成mp3格式
  17. wlan协议—802.11n—802.11ac 5G和2.4G
  18. Win10系统,如何使用系统自带截图工具 “PrintScreen键“
  19. 谁在用生命为错误买单?
  20. [转]机器学习资料(非常好理解)

热门文章

  1. 【关于Linux中----信号】
  2. web前端卡片样式_css完成卡片式图片结果_WEB前端开发
  3. 一个总经理的11个面试问题
  4. 李代沫吸毒误导青少年 应脱离娱乐圈
  5. Cocos Analytics 拍了拍你,并向你连发3条消息
  6. SD-Flasher在win7系统里面烧写SD卡的问题
  7. 一款基于Qt的俄罗斯方块游戏
  8. mysql会话和事务_MySQL事务熟练使用就够?和腾讯大佬的一席对话,原来考点都在这些方面!...
  9. 对话:人狠话不多 vs 中间件小姐姐
  10. Android launcher2 应用列表背景透明/透明壁纸