【手撕 Spring】 -- Bean 的创建以及获取
🌈手写简化版 Spring 框架:通过构建一个精简版的 Spring 框架,深入理解 Spring 的核心机制,掌握其设计思想,进一步提升编程能力
🌈项目代码地址:https://github.com/YYYUUU42/mini-Spring
如果该项目对你有帮助,可以在 github 上点个 ⭐ 喔 🥰🥰
🌈手撕 Spring 系列:可以点开专栏,参看完整的文档
目录
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
类型存储
/**
* @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 的功能
/**
* @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 管理的实现类都基于这个接
public interface BeanFactory {
Object getBean(String name) throws BeansException;
}
AbstractBeanFactory
实现了 BeanFactory
接口,提供了从容器中获取 Bean 的基础逻辑,包含单例 Bean 的管理和 Bean 创建的模板方法。它主要负责:
- 单例管理:通过从单例缓存中获取 Bean。
- 模板方法模式:定义了
createBean()
和getBeanDefinition()
的抽象方法,由子类实现具体的 Bean 创建和定义获取逻辑。
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
,并为自动装配提供了支持。
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 中管理单例对象的关键接口。
public interface SingletonBeanRegistry {
Object getSingleton(String beanName);
}
DefaultSingletonBeanRegistry
实现了 SingletonBeanRegistry
接口,提供了 Spring 容器中单例 Bean 的注册和获取功能。它维护了一个单例缓存,用于存储和管理单例 Bean
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 元数据的核心接口。
public interface BeanDefinitionRegistry {
/**
* 向注册表中注册 BeanDefinition
*/
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
}
DefaultListableBeanFactory
是 Spring 容器中最核心的实现类之一,集成了 AbstractAutowireCapableBeanFactory
、BeanDefinitionRegistry
、DefaultSingletonBeanRegistry
等多种功能。它既可以注册和管理 Bean 定义,也可以创建和管理单例 Bean。
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. 测试
public class UserService {
public void getUserInfo(){
System.out.println("得到用户信息");
}
}
@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 对象时,工厂直接从单例对象容器中获取,不再重新实例化。
3. 类图
原文地址:https://blog.csdn.net/m0_63208096/article/details/143778196
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!