🌈手写简化版 Spring 框架 **:**通过构建一个精简版的 Spring 框架,深入理解 Spring 的核心机制,掌握其设计思想,进一步提升编程能力
🌈项目代码地址: https://github.com/YYYUUU42/mini-Spring
如果该项目对你有帮助,可以在 github 上点个 ⭐ 喔 🥰🥰
🌈手撕 Spring 系列 **:**可以点开专栏,参看完整的文档
目录
[1. 创建简单的 Bean 容器](#1. 创建简单的 Bean 容器)
[1.1. Spring Bean 容器是什么](#1.1. Spring Bean 容器是什么)
[1.2. 实现思路](#1.2. 实现思路)
[1.3. 代码](#1.3. 代码)
[2. Bean 的定义、注册、获取](#2. Bean 的定义、注册、获取)
[2.1. 代码实现](#2.1. 代码实现)
[2.2. 类之间的关系](#2.2. 类之间的关系)
[2.3. 设计目的](#2.3. 设计目的)
[2.4. 测试](#2.4. 测试)
[3. 类图](#3. 类图)
1. 创建简单的 Bean 容器
1.1. Spring Bean 容器是什么
Spring 容器用于管理应用中的对象配置和生命周期,类似于一个对象的承载和管理容器。通过配置每个 Bean 的创建方式,开发者可以控制这些对象是以单例模式存在,还是每次请求时创建新的实例,以及它们之间的关联和协作方式。
当对象交给 Spring 容器管理时,它会被封装为一个 Bean。Bean 的定义将对象的属性、依赖关系等信息进行解耦,这使得 Spring 容器可以轻松管理对象,处理像循环依赖这样的复杂场景。
一旦 Bean 被定义并注册到容器中,Spring 会负责整个装配过程,包括初始化、属性注入、依赖解析等步骤。最终,Spring 容器会提供一个完全初始化的 Bean 供应用程序使用。
1.2. 实现思路
为了实现一个简单的 Spring Bean 容器,需要以下三个基本步骤:定义 、注册 和 获取。
- 定义 :
BeanDefinition
是 Spring 中常见的一个类,用于定义 Bean 的信息。在初步实现中,我们简化处理,将 Bean 以Object
类型存储。 - 注册 :这个过程类似于将数据存放到
HashMap
中,不同的是我们存放的是 Bean 的定义信息。 - 获取 :通过 Bean 的名称作为
key
,在 Spring 容器中直接获取初始化后的 Bean 对象。
1.3. 代码
BeanDefinition
用于定义 Bean 的实例化信息,当前实现将 Bean 以 Object
类型存储
java
/**
* @description 用于定义 Bean 实例化信息
*/
public class BeanDefinition {
private Object bean;
public BeanDefinition(Object bean) {
this.bean = bean;
}
public Object getBean() {
return bean;
}
}
BeanFactory
代表了 Bean 对象的工厂,负责将 Bean 的定义信息注册到 Map
中,并提供获取 Bean 的功能
java
/**
* @description 代表了 Bean 对象的工厂,可以存放 Bean 定义到 Map 中以及获取
*/
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);
}
}
2. Bean 的定义、注册、获取
2.1. 代码实现
BeanFactory
是 Spring 容器的核心接口,它定义了从容器中获取 Bean 的基本方法,如 getBean()
。这是所有 Bean 容器的顶层接口,也是 Spring IoC 容器的核心入口。所有 Bean 管理的实现类都基于这个接
java
public interface BeanFactory {
Object getBean(String name) throws BeansException;
}
AbstractBeanFactory
实现了 BeanFactory
接口,提供了从容器中获取 Bean 的基础逻辑,包含单例 Bean 的管理和 Bean 创建的模板方法。它主要负责:
- 单例管理:通过从单例缓存中获取 Bean。
- 模板方法模式 :定义了
createBean()
和getBeanDefinition()
的抽象方法,由子类实现具体的 Bean 创建和定义获取逻辑。
java
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
/**
* 从 Map 中获取单例 bean 对象
* 如果不存在则获取 bean 定义创建 bean 对象
*/
@Override
public Object getBean(String name) throws BeansException {
Object bean = getSingleton(name);
if (bean != null) {
return bean;
}
BeanDefinition beanDefinition = getBeanDefinition(name);
return createBean(name, beanDefinition);
}
/**
* 获取 bean 的定义
*/
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
/**
* 创建 bean 对象
*/
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException;
}
AbstractAutowireCapableBeanFactory
继承了 AbstractBeanFactory
,实现了 Bean 的创建逻辑,尤其是自动装配相关的功能。它通过反射机制实例化 Bean,并支持自动注入依赖。这个类扩展了 AbstractBeanFactory
,并为自动装配提供了支持。
java
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
/**
* 创建 Bean 实例并将其注册为单例
*/
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
Object bean;
try {
// 通过反射创建 Bean 实例
bean = beanDefinition.getBeanClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new BeansException("Instantiation of bean failed", e);
}
// 将创建的 Bean 注册为单例
addSingleton(beanName, bean);
return bean;
}
}
SingletonBeanRegistry
定义了 Spring 中关于单例管理的规范,允许将单例 Bean 注册到容器中,以及从容器中获取单例 Bean。它是 Spring 中管理单例对象的关键接口。
java
public interface SingletonBeanRegistry {
Object getSingleton(String beanName);
}
DefaultSingletonBeanRegistry
实现了 SingletonBeanRegistry
接口,提供了 Spring 容器中单例 Bean 的注册和获取功能。它维护了一个单例缓存,用于存储和管理单例 Bean
java
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
private final Map<String, Object> singletonObjects = new HashMap<>();
/**
* 从 Map 中获取单例对象
*/
@Override
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
/**
* 将 bean 存入 Map
*/
protected void addSingleton(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
}
BeanDefinitionRegistry
定义了 Spring 容器中管理 BeanDefinition
的基本功能,它允许向容器中注册、移除和获取 Bean 定义。这是 Spring 管理 Bean 元数据的核心接口。
java
public interface BeanDefinitionRegistry {
/**
* 向注册表中注册 BeanDefinition
*/
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
}
DefaultListableBeanFactory
是 Spring 容器中最核心的实现类之一,集成了 AbstractAutowireCapableBeanFactory
、BeanDefinitionRegistry
、DefaultSingletonBeanRegistry
等多种功能。它既可以注册和管理 Bean 定义,也可以创建和管理单例 Bean。
java
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry {
/**
* 存储 BeanDefinition 的 Map,用于注册和获取 Bean 定义
*/
private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
/**
* 将 BeanDefinition 注册到容器中。
*/
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
beanDefinitionMap.put(beanName, beanDefinition);
}
/**
* 根据名称获取 BeanDefinition,如果找不到则抛出异常。
*/
@Override
public BeanDefinition getBeanDefinition(String beanName) throws BeansException {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition == null) {
throw new BeansException("No bean named '" + beanName + "' is defined");
}
return beanDefinition;
}
}
2.2. 类之间的关系
- DefaultSingletonBeanRegistry 实现了
SingletonBeanRegistry
接口,提供单例管理的实现,AbstractBeanFactory
继承了它,获得了单例管理的能力。 - AbstractBeanFactory 实现了
BeanFactory
接口,并从DefaultSingletonBeanRegistry
继承单例管理能力。它提供了模板方法createBean()
和getBeanDefinition()
,而具体的创建 Bean 和获取 Bean 定义的逻辑由子类实现。 - AbstractAutowireCapableBeanFactory 继承自
AbstractBeanFactory
,扩展了自动装配和通过反射创建 Bean 的能力,实现了createBean()
方法。 - BeanDefinitionRegistry 是管理 Bean 定义的接口,
DefaultListableBeanFactory
实现了该接口,提供了注册和管理 Bean 定义的功能。 - DefaultListableBeanFactory 继承了
AbstractAutowireCapableBeanFactory
,因此它不仅支持创建 Bean,还可以进行自动装配和单例管理。它同时实现了BeanDefinitionRegistry
,因此可以管理 Bean 定义。
2.3. 设计目的
- 职责分离 :这些类通过分层次继承和接口实现,将不同的职责(如单例管理、Bean 创建、Bean 定义管理等)进行拆分。每个类负责一项或多项特定的功能,使得代码更具可扩展性和可维护性。例如,
DefaultSingletonBeanRegistry
专注于单例管理,而AbstractAutowireCapableBeanFactory
专注于 Bean 的创建和自动装配。 - 高内聚低耦合 :每个类只处理它所负责的核心功能,通过接口和继承来组合这些功能,从而减少类之间的耦合。例如,
AbstractBeanFactory
负责 Bean 的获取,具体的 Bean 创建逻辑交给子类AbstractAutowireCapableBeanFactory
去实现。 - 模板方法模式 :
AbstractBeanFactory
使用模板方法模式,它定义了获取和创建 Bean 的流程,但具体的实现由子类去完成。这种设计可以让代码结构清晰,并且便于扩展。 - 灵活的扩展性 :
DefaultListableBeanFactory
实现了所有这些核心功能,并结合了 Bean 的创建、注册、单例管理等功能。通过继承和接口组合的方式,Spring 可以在不影响整体设计的前提下,灵活地对某些功能进行扩展。
2.4. 测试
java
public class UserService {
public void getUserInfo(){
System.out.println("得到用户信息");
}
}
java
@Test
public void test(){
// 1.初始化 BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2.注册 bean
BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
beanFactory.registerBeanDefinition("userService", beanDefinition);
// 3.第一次获取 bean
UserService userService = (UserService) beanFactory.getBean("userService");
userService.getUserInfo();
// 4.第二次获取 bean from Singleton
UserService userServiceSingleton = (UserService) beanFactory.getSingleton("userService");
userServiceSingleton.getUserInfo();
}
调用流程
- 实例化
DefaultListableBeanFactory
对象。 - 将
UserService
类作为构造器参数,实例化一个BeanDefinition
对象。 - 使用第 1 步创建的工厂对象调用
registerBeanDefinition
方法,将第 2 步的beanDefinition
对象注册到BeanDefinitionMap
容器中。 - 通过工厂获取
UserService
的 bean 对象。首先尝试从单例对象容器中获取,如果未找到,则从BeanDefinitionMap
容器中获取UserService
类的定义并进行实例化(通过newInstance
),然后将实例化后的对象存入单例对象容器中,便于下次调用。 - 第二次调用
UserService
的 bean 对象时,工厂直接从单例对象容器中获取,不再重新实例化。