千家信息网

如何实现一个萌芽版的Spring容器

发表于:2025-11-07 作者:千家信息网编辑
千家信息网最后更新 2025年11月07日,这篇文章主要为大家展示了"如何实现一个萌芽版的Spring容器",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"如何实现一个萌芽版的Spring容器"这篇文章
千家信息网最后更新 2025年11月07日如何实现一个萌芽版的Spring容器

这篇文章主要为大家展示了"如何实现一个萌芽版的Spring容器",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"如何实现一个萌芽版的Spring容器"这篇文章吧。

从什么是IOC开始?

Spring--春天,Java编程世界的春天是由一位音乐家--Rod Johnson带来的。

Rod Johnson先后编写了两本巨著《Expert One-on-One J2EE Design and Development》、《Expert One-on-One J2EE Development without EJB》,拉起了挑战正统Java EE框架EJB的大旗。

Rod Johnson不仅是一名旗手,更是开发了Spring这一轻量级框架,像一名勇敢的龙骑兵一样,对EJB发动了冲锋,并最终战胜了EJB,让Spring成为Java EE事实上的标准。

Spring的两大内核分别是IOC和AOP,其中最最核心的是IOC。

所谓的IOC(控制反转):就是由容器来负责控制对象的生命周期和对象间的关系。以前是我们想要什么,就自己创建什么,现在是我们需要什么,容器就给我们送来什么。

也就是说,控制对象生命周期的不再是引用它的对象,而是容器。对具体对象,以前是它控制其它对象,现在所有对象都被容器控制,所以这就叫控制反转。

也许你还听到另外一个概念DI(依赖注入),它指的是容器在实例化对象的时候把它依赖的类注入给它,我们也可以认为,DI是IOC的补充和实现。

工厂和Spring容器

Spring是一个成熟的框架,为了满足扩展性、实现各种功能,所以它的实现如同枝节交错的大树一样,现在让我们把视线从Spring本身移开,来看看一个萌芽版的Spring容器怎么实现。

Spring的IOC本质就是一个大工厂,我们想想一个工厂是怎么运行的呢?

生产产品:一个工厂最核心的功能就是生产产品。在Spring里,不用Bean自己来实例化,而是交给Spring,应该怎么实现呢?——答案毫无疑问,反射。

那么这个厂子的生产管理是怎么做的?你应该也知道——工厂模式。

库存产品:工厂一般都是有库房的,用来库存产品,毕竟生产的产品不能立马就拉走。Spring我们都知道是一个容器,这个容器里存的就是对象,不能每次来取对象,都得现场来反射创建对象,得把创建出的对象存起来。

订单处理:还有最重要的一点,工厂根据什么来提供产品呢?订单。这些订单可能五花八门,有线上签签的、有到工厂签的、还有工厂销售上门签的……最后经过处理,指导工厂的出货。

在Spring里,也有这样的订单,它就是我们bean的定义和依赖关系,可以是xml形式,也可以是我们最熟悉的注解形式。

那对应我们的萌芽版的Spring容器是什么样的呢?

订单:Bean定义

Bean可以通过一个配置文件定义,我们会把它解析成一个类型。

  • beans.properties

为了偷懒,这里直接用了最方便解析的properties,用一个类型的配置来代表Bean的定义,其中key是beanName,value是class

userDao:cn.fighter3.bean.UserDao

  • BeanDefinition.java

bean定义类,配置文件中bean定义对应的实体

public class BeanDefinition {    private String beanName;    private Class beanClass;     //省略getter、setter   }

获取订单:资源加载

接下订单之后,就要由销售向生产部门交接,让生产部门知道商品的规格、数量之类。

资源加载器,就是来完成这个工作的,由它来完成配置文件中配置的加载。

public class ResourceLoader {    public static Map getResource() {        Map beanDefinitionMap = new HashMap<>(16);        Properties properties = new Properties();        try {            InputStream inputStream = ResourceLoader.class.getResourceAsStream("/beans.properties");            properties.load(inputStream);            Iterator it = properties.stringPropertyNames().iterator();            while (it.hasNext()) {                String key = it.next();                String className = properties.getProperty(key);                BeanDefinition beanDefinition = new BeanDefinition();                beanDefinition.setBeanName(key);                Class clazz = Class.forName(className);                beanDefinition.setBeanClass(clazz);                beanDefinitionMap.put(key, beanDefinition);            }            inputStream.close();        } catch (IOException | ClassNotFoundException e) {            e.printStackTrace();        }        return beanDefinitionMap;    }}

订单分配:Bean注册

对象注册器,这里用于单例bean的缓存,我们大幅简化,默认所有bean都是单例的。可以看到所谓单例注册,也很简单,不过是往HashMap里存对象。

public class BeanRegister {    //单例Bean缓存    private Map singletonMap = new HashMap<>(32);    /**     * 获取单例Bean     *     * @param beanName bean名称     * @return     */    public Object getSingletonBean(String beanName) {        return singletonMap.get(beanName);    }    /**     * 注册单例bean     *     * @param beanName     * @param bean     */    public void registerSingletonBean(String beanName, Object bean) {        if (singletonMap.containsKey(beanName)) {            return;        }        singletonMap.put(beanName, bean);    }}

生产车间:对象工厂

好了,到了我们最关键的生产部门了,在工厂里,生产产品的是车间,在IOC容器里,生产对象的是BeanFactory。

对象工厂,我们最核心的一个类,在它初始化的时候,创建了bean注册器,完成了资源的加载。

获取bean的时候,先从单例缓存中取,如果没有取到,就创建并注册一个bean

public class BeanFactory {    private Map beanDefinitionMap = new HashMap<>();    private BeanRegister beanRegister;    public BeanFactory() {        //创建bean注册器        beanRegister = new BeanRegister();        //加载资源        this.beanDefinitionMap = new ResourceLoader().getResource();    }    /**     * 获取bean     *     * @param beanName bean名称     * @return     */    public Object getBean(String beanName) {        //从bean缓存中取        Object bean = beanRegister.getSingletonBean(beanName);        if (bean != null) {            return bean;        }        //根据bean定义,创建bean        return createBean(beanDefinitionMap.get(beanName));    }    /**     * 创建Bean     *     * @param beanDefinition bean定义     * @return     */    private Object createBean(BeanDefinition beanDefinition) {        try {            Object bean = beanDefinition.getBeanClass().newInstance();            //缓存bean            beanRegister.registerSingletonBean(beanDefinition.getBeanName(), bean);            return bean;        } catch (InstantiationException | IllegalAccessException e) {            e.printStackTrace();        }        return null;    }}

生产销售:测试

UserDao.java

我们的Bean类,很简单

public class UserDao {    public void queryUserInfo(){        System.out.println("A good man.");    }}

单元测试

public class ApiTest {    @Test    public void test_BeanFactory() {        //1.创建bean工厂(同时完成了加载资源、创建注册单例bean注册器的操作)        BeanFactory beanFactory = new BeanFactory();        //2.第一次获取bean(通过反射创建bean,缓存bean)        UserDao userDao1 = (UserDao) beanFactory.getBean("userDao");        userDao1.queryUserInfo();        //3.第二次获取bean(从缓存中获取bean)        UserDao userDao2 = (UserDao) beanFactory.getBean("userDao");        userDao2.queryUserInfo();    }}

运行结果

A good man.
A good man.

至此,我们一个萌芽版的Spring容器就完成了。

以上是"如何实现一个萌芽版的Spring容器"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

对象 容器 工厂 生产 订单 产品 缓存 控制 就是 资源 配置 内容 文件 时候 核心 框架 篇文章 部门 反射 销售 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 计算机网络安全专业有哪些学校 天津网络技术咨询指导 互联网网络安全研究院 数据库服务器方案 数据库查询用户所在部门 为什么软件开发转实施 班级群网络安全提醒简短 服务器硬件型号 数据库索引的四种类型 三丰云服务器地址 计算机三级网络技术每题分数 商超网络技术有限公司怎么样 云服务器销售腾讯 小型互联网科技公司财务问题 拱墅计算机网络技术咨询服务 软件开发客服有什么要求 网络安全宝典图片 软件开发收入算劳务收入吗 浙江发展软件开发项目信息 软件开发生命周期的步骤 数据库数据量情况描述 网络安全建设紧迫性 新纪元软件搜索数据库 贵州省研发什么服务器云主机 贵州通信软件开发服务价钱 软件开发和产品怎么合作 临床公共数据库可以发文章吗 北京展厅互动软件开发 豆豆柴服务器在哪里 网络技术和数据库哪个容易考
0