【手撕 Spring】 -- Bean 的创建以及获取

🌈手写简化版 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 容器,需要以下三个基本步骤:定义注册获取

  1. 定义BeanDefinition 是 Spring 中常见的一个类,用于定义 Bean 的信息。在初步实现中,我们简化处理,将 Bean 以 Object 类型存储。
  2. 注册 :这个过程类似于将数据存放到 HashMap 中,不同的是我们存放的是 Bean 的定义信息。
  3. 获取 :通过 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 容器中最核心的实现类之一,集成了 AbstractAutowireCapableBeanFactoryBeanDefinitionRegistryDefaultSingletonBeanRegistry 等多种功能。它既可以注册和管理 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. 类之间的关系

  1. DefaultSingletonBeanRegistry 实现了 SingletonBeanRegistry 接口,提供单例管理的实现,AbstractBeanFactory 继承了它,获得了单例管理的能力。
  2. AbstractBeanFactory 实现了 BeanFactory 接口,并从 DefaultSingletonBeanRegistry 继承单例管理能力。它提供了模板方法 createBean()getBeanDefinition(),而具体的创建 Bean 和获取 Bean 定义的逻辑由子类实现。
  3. AbstractAutowireCapableBeanFactory 继承自 AbstractBeanFactory,扩展了自动装配和通过反射创建 Bean 的能力,实现了 createBean() 方法。
  4. BeanDefinitionRegistry 是管理 Bean 定义的接口,DefaultListableBeanFactory 实现了该接口,提供了注册和管理 Bean 定义的功能。
  5. DefaultListableBeanFactory 继承了 AbstractAutowireCapableBeanFactory,因此它不仅支持创建 Bean,还可以进行自动装配和单例管理。它同时实现了 BeanDefinitionRegistry,因此可以管理 Bean 定义。

2.3. 设计目的

  1. 职责分离 :这些类通过分层次继承和接口实现,将不同的职责(如单例管理、Bean 创建、Bean 定义管理等)进行拆分。每个类负责一项或多项特定的功能,使得代码更具可扩展性和可维护性。例如,DefaultSingletonBeanRegistry 专注于单例管理,而 AbstractAutowireCapableBeanFactory 专注于 Bean 的创建和自动装配。
  2. 高内聚低耦合 :每个类只处理它所负责的核心功能,通过接口和继承来组合这些功能,从而减少类之间的耦合。例如,AbstractBeanFactory 负责 Bean 的获取,具体的 Bean 创建逻辑交给子类 AbstractAutowireCapableBeanFactory 去实现。
  3. 模板方法模式AbstractBeanFactory 使用模板方法模式,它定义了获取和创建 Bean 的流程,但具体的实现由子类去完成。这种设计可以让代码结构清晰,并且便于扩展。
  4. 灵活的扩展性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();
}

调用流程

  1. 实例化 DefaultListableBeanFactory 对象。
  2. UserService 类作为构造器参数,实例化一个 BeanDefinition 对象。
  3. 使用第 1 步创建的工厂对象调用 registerBeanDefinition 方法,将第 2 步的 beanDefinition 对象注册到 BeanDefinitionMap 容器中。
  4. 通过工厂获取 UserService 的 bean 对象。首先尝试从单例对象容器中获取,如果未找到,则从 BeanDefinitionMap 容器中获取 UserService 类的定义并进行实例化(通过 newInstance),然后将实例化后的对象存入单例对象容器中,便于下次调用。
  5. 第二次调用 UserService 的 bean 对象时,工厂直接从单例对象容器中获取,不再重新实例化。

3. 类图

相关推荐
suweijie7682 小时前
SpringCloudAlibaba | Sentinel从基础到进阶
java·大数据·sentinel
公贵买其鹿3 小时前
List深拷贝后,数据还是被串改
java
LCG元6 小时前
【面试问题】JIT 是什么?和 JVM 什么关系?
面试·职场和发展
向前看-6 小时前
验证码机制
前端·后端
xlsw_6 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹7 小时前
基于java的改良版超级玛丽小游戏
java
油泼辣子多加8 小时前
2024年12月18日Github流行趋势
github
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭8 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
hunteritself8 小时前
AI Weekly『12月16-22日』:OpenAI公布o3,谷歌发布首个推理模型,GitHub Copilot免费版上线!
人工智能·gpt·chatgpt·github·openai·copilot
暮湫8 小时前
泛型(2)
java