文章目录
- 一、目标:创建简单的Bean容器
- 二、设计:创建简单的Bean容器
- 三、实现:创建简单的Bean容器
- 3.0 引入依赖
- 3.1 工程结构
- 3.2 创建简单Bean容器类图
- 3.3 Bean定义
- 3.4 Bean工厂
- 四、测试:创建简单的Bean容器
- 4.1 用户Bean对象
- 4.2 单元测试
- 五、总结:创建简单的Bean容器
一、目标:创建简单的Bean容器
💡 Spring Bean 容器是什么?
- Spring 包含并管理应用对象的配置和生命周期,在这个意义上它是一种用于承载对象的容器。
- 你可以配置你的每个 Bean 对象是如何被创建的。
- 这些 Bean 可以创建一个单独的实例或者每次需要时都生成一个新的实例,以及它们是如何相互关联构建和使用的。
- 如果一个 Bean 对象交给 Spring 容器管理,那么这个 Bean 对象就应该以类似零件的方式被拆解后存放到 Bean 的定义中。
- 这样相当于一种把对象解耦的操作,可以由 Spring 更加容易的管理,就像处理循环依赖等操作。
- 当一个 Bean 对象被定义存放以后,再由 Spring 统一进行装配,这个过程包括:Bean 的初始化、属性填充等。
- 最终我们就可以完整的使用一个 Bean 实例化后的对象了。
- 目标:定义一个简单的 Spring 容器,用于定义、存放和获取 Bean 对象。
二、设计:创建简单的Bean容器
💡 简单的 Spring Bean 容器如何实现?
- 凡是可以存放数据的具体数据结构实现,都可以称之为容器。
- 例如:
ArrayList
、LinkedList
、HashSet
等。 - 但在 Spring Bean 容器的场景下,我们需要一种可以用于存放和名称索引式的数据结构,
HashMap
是最合适的。
- 例如:
HashMap
:是一种基于扰动函数、负载因子、红黑树转换等技术内容,形成的拉链寻址的数据结构。- 它能让数据更加散列的分布在哈希桶以及碰撞时形成的链表和红黑树上。
- 它的数据结构会尽可能最大限度的让整个数据读取的复杂度在
O(1)~O(Logn)~O(n)
之间。 - 当日在极端情况下也会有
O(n)
链表查找数据较多的情况,不过我们经过10万数据的扰动函数再寻址验证测试,数据会均匀的散列在各个哈希桶索引上。 - 所以
HashMap
非常适合用在 Spring Bean 的容器实现上。
- 一个简单的 Spring Bean 容器实现,还需 Bean 的定义、注册、获取三个基本步骤。
- 定义:
BeanDefinition
,它会包括singleton、prototype、BeanClassName
等。目前初步实现一个 Object 类型用于存放对象。 - 注册:这个过程就相当于我们把数据存放到
HashMap
中,只不过现在HashMap
存放的是定义了的 Bean 对象信息。 - 获取:最后就是获取对象,Bean 的名字就是
key
,Spring 容器初始化好 Bean 以后,就可以直接获取了。
三、实现:创建简单的Bean容器
3.0 引入依赖
pom.xml
<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency>
</dependencies>
3.1 工程结构
spring-step-01
|-src|-main| |-java| |-com.lino.springframework| |-BeanDefinition.java| |-BeanFactory.java|-test|-java|-com.lino.springframework.test|-bean| |-UserService.java|-ApiTest.java
3.2 创建简单Bean容器类图
- Spring Bean 容器的整个实现内容非常简单,也仅仅是包括了一个简单的 BeanFactory 和 BeanDefinition。
- 这里的类名称是与 Spring 源码中一致,只不过现在的类实现会相对来说更简化一些,在后续的实现再继续添加内容。
- BeanFactory:用于定义 Bean 实例化信息,现在的实现是一个 Object 存放对象。
- BeanDefinition:代表了 Bean 对象的工厂,可以存放 Bean 定义到 Map 中以及获取。
3.3 Bean定义
BeanDefinition.java
package com.lino.springframework;/*** @description: Bean 对象信息定义*/
public class BeanDefinition {/*** bean对象*/private Object bean;public BeanDefinition(Object bean) {this.bean = bean;}public Object getBean() {return bean;}
}
- 目前的 Bean 定义中,只有一个 Object 用于存放 Bean 对象。
- 在后续的实现中会逐步完善 BeanDefinition 相关属性的填充。
- 例如:
SCOPE_SINGLETON、SCOPE_PROTOTYPE、ROLE_APPLICATION、ROLE_SUPPORT、ROLE_INFRASTRUCTURE
以及 Bean Class 信息。
- 例如:
3.4 Bean工厂
BeanFactory.java
package com.lino.springframework;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @description: 简单的 Bean 工厂*/
public class BeanFactory {/*** bean对象Map*/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 使用的最终体现结果。
- 只不过实现过程只展示出基本的核心原理。
四、测试:创建简单的Bean容器
4.1 用户Bean对象
UserService.java
package com.lino.springframework.test.bean;/*** @description: 模拟用户 Bean 对象*/
public class UserService {/*** 查询用户信息*/public void queryUserInfo() {System.out.println("查询用户信息");}
}
- 定义一个 UserService 对象。
4.2 单元测试
ApiTest.java
package com.lino.springframework.test;import com.lino.springframework.BeanDefinition;
import com.lino.springframework.BeanFactory;
import com.lino.springframework.test.bean.UserService;
import org.junit.Test;/*** @description: 测试类*/
public class ApiTest {@Testpublic void test_BeanFactory() {// 1.初始化 BeanFactoryBeanFactory beanFactory = new BeanFactory();// 2.注入beanBeanDefinition beanDefinition = new BeanDefinition(new UserService());beanFactory.registerBeanDefinition("userService", beanDefinition);// 3.获取beanUserService userService = (UserService) beanFactory.getBean("userService");userService.queryUserInfo();}
}
- 在单元测试中主要包括 初始化 Bean 工厂、注册 Bean、获取 Bean 三个步骤。
- 在 Bean 的注册中,这里是直接把 UserService 实例化后作为入参传递给 BeanDefinition 的,在后续的陆续实现中,这部分会放入 Bean 工厂中实现。
测试结果
查询用户信息
- 通过测试结果看是正常通过的。
五、总结:创建简单的Bean容器
- 整篇关于 Spring Bean 容器的一个雏形就已经实现完成了。
- 相对于一个知识的学习来说,写代码只是最后的步骤,往往整个思路、设计、方案,才更重要,只要你知道了因为什么,所以什么,才能让你有一个真正的理解。