千家信息网

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

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章主要为大家展示了"如何实现一个萌芽版的Spring容器",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"如何实现一个萌芽版的Spring容器"这篇文章
千家信息网最后更新 2026年11月01日如何实现一个萌芽版的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安全错误 数据库的锁怎样保障安全 什么是科技互联网 互联网科技图片 广州大一互联网络科技有限公司 互联网科技公司经营范围 金融科技 互联网金融 互联网科技视频 苏州互联网科技贷款公司 互联网科技美容 互联网校园科技培训 受益于互联网科技的高速发展 湖南一路畅行互联网科技 米聚互联网科技南京有限公司排面 众安科技工业互联网合作 广东工业互联网大赛深圳学泰科技 城市宝互联网科技有限公司 领航科技大厦互联网公司 萌小萌互联网科技河南有限公司 互联网金融运营模式中的金融科技 米泉互联网科技专业怎么样 每日互联网科技新闻 互联网科技工作委员会主任 互联网科技公司电话 北京禾田雨橡互联网科技 互联网科技小额贷款 掌上梦互联网科技 新华互联网科技2019 燊美集互联网科技有限公司 华夏恒生互联网科技013171 长沙渺峰互联网科技有限公司 银川新华互联网科技学校招聘
0