小试牛刀,实现一个简单的Bean容器!

人工智能2025-11-05 13:03:312437

 一、小试牛刀前言

上学时,实现老师总说:不会你就问,个简但多数时候都不知道要问什么!

你总会在小傅哥的容器文章前言里,发现一些关于成长、小试牛刀学习、实现感悟以及对当篇内容的个简一个介绍,其实之所以写这样的容器铺垫性内容,主要是小试牛刀为了让大家对接下来的内容学习有一个较轻松的开场和过度。

就像我们上学时如果某一科的实现内容不会时,老师经常会说,个简你有不会的容器就要问。但对于学生本身来讲,小试牛刀可能已经不会的实现太多了,或者压根不知道自己不会什么,个简只有等看到老师出完的试卷才发现自己什么都不会。但要是让问,又不知道从哪问,问出萝卜带出泥,到处都是知识漏洞。

所以我希望用一些前置内容的铺垫,云服务器提供商让大家可以在一个稍有共识的场景下进行学习,或多或少能为你铺垫出一个稍许平缓的接受期。有可能某些时候也会打打鸡血、刺激刺激学习、总归把知识学到手就是好的!

二、目标

Spring Bean 容器是什么?

Spring 包含并管理应用对象的配置和生命周期,在这个意义上它是一种用于承载对象的容器,你可以配置你的每个 Bean 对象是如何被创建的,这些 Bean 可以创建一个单独的实例或者每次需要时都生成一个新的实例,以及它们是如何相互关联构建和使用的。

如果一个 Bean 对象交给 Spring 容器管理,那么这个 Bean 对象就应该以类似零件的方式被拆解后存放到 Bean 的定义中,这样相当于一种把对象解耦的操作,可以由 Spring 更加容易的管理,站群服务器就像处理循环依赖等操作。

当一个 Bean 对象被定义存放以后,再由 Spring 统一进行装配,这个过程包括 Bean 的初始化、属性填充等,最终我们就可以完整的使用一个 Bean 实例化后的对象了。

而我们本章节的案例目标就是定义一个简单的 Spring 容器,用于定义、存放和获取 Bean 对象。

三、设计

凡是可以存放数据的具体数据结构实现,都可以称之为容器。例如:ArrayList、LinkedList、HashSet等,但在 Spring Bean 容器的场景下,我们需要一种可以用于存放和名称索引式的数据结构,所以选择 HashMap 是最合适不过的。

这里简单介绍一下 HashMap,HashMap 是一种基于扰动函数、高防服务器负载因子、红黑树转换等技术内容,形成的拉链寻址的数据结构,它能让数据更加散列的分布在哈希桶以及碰撞时形成的链表和红黑树上。它的数据结构会尽可能最大限度的让整个数据读取的复杂度在 O(1) ~ O(Logn) ~O(n)之间,当然在极端情况下也会有 O(n) 链表查找数据较多的情况。不过我们经过10万数据的扰动函数再寻址验证测试,数据会均匀的散列在各个哈希桶索引上,所以 HashMap 非常适合用在 Spring Bean 的容器实现上。

另外一个简单的 Spring Bean 容器实现,还需 Bean 的定义、注册、获取三个基本步骤,简化设计如下;

定义:BeanDefinition,可能这是你在查阅 Spring 源码时经常看到的一个类,例如它会包括 singleton、prototype、BeanClassName 等。但目前我们初步实现会更加简单的处理,只定义一个 Object 类型用于存放对象。

注册:这个过程就相当于我们把数据存放到 HashMap 中,只不过现在 HashMap 存放的是定义了的 Bean 的对象信息。

获取:最后就是获取对象,Bean 的名字就是key,Spring 容器初始化好 Bean 以后,就可以直接获取了。

接下来我们就按照这个设计,做一个简单的 Spring Bean 容器代码实现。编码的过程往往并不会有多复杂,但知晓设计过程却更加重要!

四、实现

1. 工程结构

small-spring-step-01 └── src     ├── main     │   └── java     │       └── cn.bugstack.springframework     │           ├── BeanDefinition.java     │           └── BeanFactory.java     └── test         └── java             └── cn.bugstack.springframework.test                   ├── bean                 │   └── UserService.java                                 └── ApiTest.java 

工程源码:https://github.com/small-spring/small-spring-step-01 (公众号:bugstack虫洞栈,回复:Spring 专栏,获取整套源码)

Spring Bean 容器类关系,如图 2-2

图 2-2

Spring Bean 容器的整个实现内容非常简单,也仅仅是包括了一个简单的 BeanFactory 和 BeanDefinition,这里的类名称是与 Spring 源码中一致,只不过现在的类实现会相对来说更简化一些,在后续的实现过程中再不断的添加内容。 BeanDefinition,用于定义 Bean 实例化信息,现在的实现是以一个 Object 存放对象

BeanFactory,代表了 Bean 对象的工厂,可以存放 Bean 定义到 Map 中以及获取。

2. Bean 定义

public class BeanDefinition {     private Object bean;     public BeanDefinition(Object bean) {         this.bean = bean;     }     public Object getBean() {         return bean;     } }  目前的 Bean 定义中,只有一个 Object 用于存放 Bean 对象。如果感兴趣可以参考 Spring 源码中这个类的信息,名称都是一样的。 不过在后面陆续的实现中会逐步完善 BeanDefinition 相关属性的填充,例如:SCOPE_SINGLETON、SCOPE_PROTOTYPE、ROLE_APPLICATION、ROLE_SUPPORT、ROLE_INFRASTRUCTURE 以及 Bean Class 信息。

3. Bean 工厂

public class BeanFactory {     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 使用的最终体现结果,只不过实现过程只展示出基本的核心原理。在后续的补充实现中,这个会不断变得庞大。

五、测试

1. 事先准备

public class UserService {     public void queryUserInfo(){         System.out.println("查询用户信息");     } } 

这里简单定义了一个 UserService 对象,方便我们后续对 Spring 容器测试。

2. 测试用例

@Test public void test_BeanFactory(){     // 1.初始化 BeanFactory     BeanFactory beanFactory = new BeanFactory();     // 2.注册 bean     BeanDefinition beanDefinition = new BeanDefinition(new UserService());     beanFactory.registerBeanDefinition("userService", beanDefinition);     // 3.获取 bean     UserService userService = (UserService) beanFactory.getBean("userService");     userService.queryUserInfo(); } 

在单测中主要包括初始化 Bean 工厂、注册 Bean、获取 Bean,三个步骤,使用效果上贴近与 Spring,但显得会更简化。

在 Bean 的注册中,这里是直接把 UserService 实例化后作为入参传递给 BeanDefinition 的,在后续的陆续实现中,我们会把这部分内容放入 Bean 工厂中实现。

3. 测试结果

查询用户信息 Process finished with exit code 0 

通过测试结果可以看到,目前的 Spring Bean 容器案例,已经稍有雏形。

六、总结

整篇关于 Spring Bean 容器的一个雏形就已经实现完成了,相对来说这部分代码并不会难住任何人,只要你稍加尝试就可以接受这部分内容的实现。 但对于一个知识的学习来说,写代码只是最后的步骤,往往整个思路、设计、方案,才更重要,只要你知道了因为什么、所以什么,才能让你有一个真正的理解。 下一章节会在此工程基础上扩容实现,要比现在的类多一些。不过每一篇的实现上,我都会以一个需求视角进行目标分析和方案设计,让大家在学习编码之外更能注重更多技术价值的学习。
本文地址:http://www.bhae.cn/html/912c29798790.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

全站热门

本文记录配置Linux服务器的初步流程,也就是系统安装完成后,下一步要做的事情。这主要是我自己的总结和备忘,假如有遗漏,欢迎大家补充。下面的操作针对Debian/Ubuntu系统,其他Linux系统也类似,就是部分命令稍有不同。 第一步:root用户登录 首先,使用root用户登录远程主机(假定IP地址是128.199.209.242)。 ssh root@128.199.209.242这时,命令行会出现警告,表示这是一个新的地址,存在安全风险。键入yes,表示接受。然后,就应该可以顺利登入远程主机。接着,修改root用户的密码。 passwd第二步:新建用户 首先,添加一个用户组(这里假定为admin用户组)。 addgroup admin然后,添加一个新用户(假定为bill)。useradd -d /home/bill -s /bin/bash -m bill 上面命令中,参数d指定用户的主目录,参数s指定用户的shell,参数m表示假如该目录不存在,则创建该目录。接着,设置新用户的密码。 passwd bill 将新用户(bill)添加到用户组(admin)。usermod -a -G admin bill 接着,为新用户设定sudo权限。visudovisudo命令会打开sudo设置文件/etc/sudoers,找到下面这一行。root ALL=(ALL:ALL) ALL在这一行的下面,再添加一行。root ALL=(ALL:ALL) ALLbill ALL=(ALL) NOPASSWD: ALL上面的NOPASSWD表示,切换sudo的时候,不需要输入密码,我喜欢这样比较省事。假如出于安全考虑,也可以强制要求输入密码。root ALL=(ALL:ALL) ALLbill ALL=(ALL:ALL) ALL然后,先退出root用户的登录,再用新用户的身份登录,检查到这一步为止,是否一切正常。exitssh bill@128.199.209.242第三步:SSH设置 首先,确定本机有SSH公钥(一般是文件~/.ssh/id_rsa.pub),假如没有的话,使用ssh-keygen命令生成一个(可参考我写的SSH教程)。 在本机上另开一个shell窗口,将本机的公钥拷贝到服务器的authorized_keys文件。 cat ~/.ssh/id_rsa.pub | ssh bill@128.199.209.242 mkdir -p .ssh && cat - >>~/.ssh/authorized_keys# 或者在服务器端,运行下面命令echo ssh-rsa [your public key] >~/.ssh/authorized_keys然后,进入服务器,编辑SSH配置文件/etc/ssh/sshd_config。sudo cp /etc/ssh/sshd_config ~sudo nano /etc/ssh/sshd_config在配置文件中,将SSH的默认端口22改掉,可以改成从1025到65536之间的任意一个整数(这里假定为25000)。Port 25000然后,检查几个设置是否设成下面这样,确保去除前面的#号。Protocol 2PermitRootLogin noPermitEmptyPasswords noPasswordAuthentication noRSAAuthentication yesPubkeyAuthentication yesAuthorizedKeysFile .ssh/authorized_keysUseDNS no上面主要是禁止root用户登录,以及禁止用密码方式登录。接着,在配置文件的末尾,指定允许登陆的用户。 AllowUsers bill保存后,退出文件编辑。接着,改变authorized_keys文件的权限。 sudo chmod 600 ~/.ssh/authorized_keys && chmod 700 ~/.ssh/然后,重启SSHD。sudo service ssh restart# 或者sudo /etc/init.d/ssh restart下面的一步是可选的。在本机~/.ssh文件夹下创建config文件,内容如下。Host s1HostName 128.199.209.242User billPort 25000最后,在本机另开一个shell窗口,测试SSH能否顺利登录。ssh s1第四步:运行环境配置 首先,检查服务器的区域设置。 locale假如结果不是en_US.UTF-8,建议都设成它。sudo locale-gen en_US en_US.UTF-8 en_CA.UTF-8sudo dpkg-reconfigure locales然后,更新软件。sudo apt-get updatesudo apt-get upgrade最后,再根据需要,做一些安全设置,比如搭建防火墙,关闭HTTP、HTTPs、SSH以外的端口,这里就不一一介绍了,谢谢阅读,希望能帮到大家,请继续关注脚本之家,我们会努力分享更多优秀的文章。

MySQL索引原理与应用:索引类型,存储结构与锁

如何在SQL Server查询中实现高效分页

《SpringCloud Alibaba实战》服务治理:实现服务调用的负载均衡

电脑进入U盘启动模式的方法(轻松学会通过简易步骤进入U盘启动模式)

浅谈RTA广告,你明白几分?

系统设计:微服务重试机制

教你如何在 Spring BOOT 中处理配置

热门文章

友情链接

滇ICP备2023000592号-9