深入理解spring源码 Day01 ( 自己手写一个Bean容器吧!)-CSDN博客

33 阅读4分钟

深入理解spring源码 Day01

1. Spring Bean容器是什么

我们先了解一下什么是容器,在Java中凡是可以存放数据的具体数据结构的实现都可以称之为容器。像ArrayList、LinkedList、HashSet等。Spring Bean容器也一样,用来存放Spring框架中最基础的Bean对象。

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

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

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

2. 设计

因为是我们自己为了更好的了解Spring的实现原理,所以我们由浅入深来实现,这里我们只是先最基础的功能。

在Spring Bean容器场景下,我们需要一种可以存放名称索引式结构,所以毫无疑问,HashMap是最合适不过的。
另外,一个简单的Spring Bean容器是西安,还需要Bean的定义、注册、获取三个基本步骤,简单设计如下:
在这里插入图片描述

  • 定义:BeanDefinition,可能这是我们在看Spring源码时经常看到的一个类,例如它会包括singleton、prototype、BeanClassName等。但是目前我们初步实现会更加简单,只会定义一个Object类型用于存放对象。
  • 注册:这个过程就相当于我们把数据存放到HashMap中,只不过现在HashMap存放的是定义了的Bean的对象信息。
  • 获取:最后就是获取对象,Bean的名字就是key,Spring容器初始化好Bean以后,就可以直接获取了。
    接下来,开干!!!

2.1 Bean的定义

package cn.zrq.springframeowrk;

/**
 * @author zrq
 * @ClassName BeanDefinition
 * @date 2023/3/19 21:01
 * @Description TODO
 */
public class BeanDefinition {
    private Object bean;

    public BeanDefinition(Object bean) {
        this.bean = bean;
    }

    public Object getBean() {
        return bean;
    }

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

2.2 Bean 工厂

package cn.zrq.springframeowrk;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @author zrq
 * @ClassName BeanFactory
 * @date 2023/3/19 21:02
 * @Description TODO
 */
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使用的最终体现结果,只不过实现过程只展示出基本的核心原理。在后续的补充实现中,这个会不断变得庞大。

2.3 测试

package cn.zrq.springframeowrk.test;

import cn.zrq.springframeowrk.BeanDefinition;
import cn.zrq.springframeowrk.BeanFactory;
import cn.zrq.springframeowrk.service.UserService;

/**
 * @author zrq
 * @ClassName ApiTest
 * @date 2023/3/19 21:12
 * @Description TODO
 */
public class ApiTest {
    //初始化BeanFactory
    private static BeanFactory beanFactory = new BeanFactory();
    private static BeanDefinition beanDefinition = new BeanDefinition(new UserService());
    public static void main(String[] args) {
        //注册Bean
        beanFactory.registerBeanDefinition("userService",beanDefinition);
        //获取Bean
        UserService userService = (UserService)beanFactory.getBean("userService");

    }
}
  • 在测试中主要包括初始化Bean工厂,注册Bean、获取Bean,三个步骤,使用效果上贴近于Spring,但会显得更简化。
  • 在Bean的注册中,这里是直接把UserService实例化后作为参数传递给BeanDefinition的,在后续的视线中,我们会把这部分内容放入Bean工厂中实现。

2.4 测试结果

在这里插入图片描述

成功啦!