手把手带你写一个 MiniSpring
郭屹
前 Sun Microsystems Java 研发工程师,开源软件 MiniSpring、MiniTomcat 开发者
6170 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 26 讲
手把手带你写一个 MiniSpring
15
15
1.0x
00:00/00:00
登录|注册

01|原始IoC:如何通过BeanFactory实现原始版本的IoC容器?

你好,我是郭屹,从今天开始我们来学习手写 MiniSpring。
这一章,我们将从一个最简单的程序开始,一步步堆积演化,最后实现 Spring 这一庞大框架的核心部分。这节课,我们就来构造第一个程序,也是最简单的一个程序,将最原始的 IoC 概念融入我们的框架之中,我们就用这个原始的 IoC 容器来管理一个 Bean。不过要说的是,它虽然原始,却也是一个可以运行的 IoC 容器。

IoC 容器

如果你使用过 Spring 或者了解 Spring 框架,肯定会对 IoC 容器有所耳闻。它的意思是使用 Bean 容器管理一个个的 Bean,最简单的 Bean 就是一个 Java 的业务对象。在 Java 中,创建一个对象最简单的方法就是使用 new 关键字。IoC 容器,也就是 BeanFactory,存在的意义就是将创建对象与使用对象的业务代码解耦让业务开发人员无需关注底层对象(Bean)的构建和生命周期管理,专注于业务开发。
那我们可以先想一想,怎样实现 Bean 的管理呢?我建议你不要直接去参考 Spring 的实现,那是大树长成之后的模样,复杂而庞大,令人生畏。
作为一颗种子,它其实可以非常原始、非常简单。实际上我们只需要几个简单的部件:我们用一个部件来对应 Bean 内存的映像,一个定义在外面的 Bean 在内存中总是需要有一个映像的;一个 XML reader 负责从外部 XML 文件获取 Bean 的配置,也就是说这些 Bean 是怎么声明的,我们可以写在一个外部文件里,然后我们用 XML reader 从外部文件中读取进来;我们还需要一个反射部件,负责加载 Bean Class 并且创建这个实例;创建实例之后,我们用一个 Map 来保存 Bean 的实例;最后我们提供一个 getBean() 方法供外部使用。我们这个 IoC 容器就做好了。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了如何通过BeanFactory实现原始版本的IoC容器。作者从最简单的程序开始,一步步演化,最终实现了Spring框架的核心部分。IoC容器的作用是使用Bean容器管理业务对象,将创建对象与使用对象的业务代码解耦。文章提出了构建IoC容器的几个简单部件:Bean内存映像、XML reader、反射部件和Map。作者首先构建了BeanDefinition类,用于定义Bean的id和class。接着实现了ClassPathXmlApplicationContext类,通过解析XML文件获取Bean的配置信息,并利用反射创建Bean实例。最后,作者通过测试代码验证了容器的功能。文章强调了通过手写MiniSpring来学习Spring框架,尽量少依赖第三方包,以原始方式写程序,以便更好地理解底层原理。通过本文,读者可以了解到如何实现一个最原始的IoC容器,以及构建IoC容器的基本步骤和原理。文章还介绍了对ClassPathXmlApplicationContext进行解耦的优化扩展工作,包括定义BeansException、BeanFactory、Resource、ClassPathXmlResource和XmlBeanDefinitionReader等。通过这些步骤,读者可以了解如何构建一个简单的IoC容器,以及如何实现功能解耦,使容器的结构更加清晰明了,便于扩展适配更多的场景。整体而言,本文为读者提供了一个简单而具有基本功能的IoC容器种子,为后续添加更多功能奠定了基础。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《手把手带你写一个 MiniSpring》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(68)

  • 最新
  • 精选
  • 6点无痛早起学习的和尚
    内容讲的很清晰,点赞。 这里有几个建议: 1. 每次代码设计之前,能否通过一个 UML 类图来表示,通过类图感觉更容易懂整个类与类之前的关系 2. 发现课程的内容还是有点偏向 Spring 那种感觉,就是有点类似:啊,Spring 是这样拆分几个类功能,那我们就这样拆分,这个方式感觉还是有点死板 感觉应该是:从一个设计者角度来讲,这样拆分更灵活,扩展性更强,叭叭叭等等,这样才能把读者带入进入课程,产生共鸣。 个人想法,欢迎交流,不知道是不是就我自己有这样感受,还是其他....

    作者回复: 好建议,我会考虑考虑。 这个课程其实最早并不是教程,就是我自己手写Spring框架时的步骤,我当年用了29天时间,一天天搭建出来的。所以现在这个课程就是按照这个次序讲解的,可能是自己写的,觉得很自然。感谢你的建议。

    2023-03-13归属地:北京
    35
  • 姐姐
    从最初的简单ApplicationContext拆解成后面的复杂ApplicationContext,我理解起来还是有困难的,努力理解如下,大神勿喷:1 readxml方法从资源文件读取内容并存入beanDefinitions,这件事情有两个地方不确定,资源的来源不同、资源的格式不同,抽象的Resource的接口,它的不同子类从不同的来源读取,但是最终都是以Resource接口的形式提供给外部访问的,这样解决了第一个不确定来源的问题;但是resource接口中被迭代的object又是根据不同格式不同而不同的,element只是xml格式的,所以又定义了BeanDefinitionReader接口,它的不同子类可以读取不同格式的资源来形成beanDefinition 。 2 . instanceBeans方法取消了 。 3. getBean方法功能增强了,不仅是获得bean,对于未创建的bean还要创建bean 4 新的applicationContext负责组装,可以根据它的名字来体现它的组装功能,例如ClassPathXmlApplicationContext 它组装的Resource的实现类是ClassPathXmlResource ,然后因为是xml的,所以需要BeanDefinitionReader的实现类XmlBeanDefinitionReader来读取并注册进beanFactory,同时ApplicationContext也提供了getBean底层调用beanfactory的实现,提供了registerBeanDefinition 来向底层的beanFactory注册bean。5 beanFactory 提供了registerBeanDefinition和getBean接口,这样无论是applicationContext还是beanDefinitionReader都可以向它注册beanDefinition,只要向它注册了,就可以调用它的getBean方法,我一直很纠结为什么不是beanfactory调用不同的beanDefinitionReader,写完这些,好像有点理解了,这样beanfactory就很专注自己的getBean方法,别的组件要怎么注入,它都不管了。

    作者回复: 你这个总结,是我见到的最详细的了,真用心。学完一遍必定大有收获。

    2023-03-22归属地:浙江
    4
    17
  • adelyn
    请问会不会穿插讲一下用到的设计模式,单独学设计模式总是学不扎实,如果能讲到就太好了

    作者回复: 会穿插讲到。确实如你所说,单独学设计模式总是会隔。

    2023-03-13归属地:北京
    4
    16
  • 风轻扬
    说一下自己对思考题的理解。 控制反转。 控制:java对象创建的控制权。 反转:将java对象创建的控制权从程序员手中反转到IOC容器手中。 另外,说一下学完这一讲的感受。直白点说,很激动。我看过Spring这部分的源码,当时感觉挺简单的,并没有往深处想,其实忽略了“Spring为什么要这样写“的问题,现在感觉这才是源码的核心所在,突然有一点融会贯通的感觉,感觉很好。一直知道Spring的扩展性好,今天实实在在看到了。感谢老师传道解惑

    作者回复: 赞!用心的程序员会爬上高峰。

    2023-03-15归属地:北京
    13
  • 未聞花名
    给老师个建议,可以点一下为什么类中要放这些属性和方法,突然抽到几个新类感觉过渡有点快,这样对之后自己去设计类也能举一反三,感觉自己平时设计不太好,如果自己实现起来的话比Spring的优雅可读性要差很多。 最后附上dom4j的maven依赖,希望帮助到其他人 ```java <!-- https://mvnrepository.com/artifact/dom4j/dom4j --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> ```

    作者回复: 感谢感谢!

    2023-03-18归属地:北京
    9
  • 杨松
    老师这句话没理解呢:“我们用一个部件来对应 Bean 内存的映像”,文中5边型图片对应的其他4个都能理解

    作者回复: 看的很细,感谢。这是书面语表达的理解问题,用我们程序员的口语来说就是“对一个Bean的定义,需要有一个类来对应。bean的定义可能是写在外部XML文件中的,类是运行时在内存中的,所以表达成Bean内存的映像”

    2023-03-14归属地:辽宁
    3
    6
  • 周润发
    首先很感谢老师的课程,内容值得细品。 想请教一个问题,为什么在代码中更多使用全局变量而不在方法中使用成员变量呢?有些全局变量只在某个方法会用到,有什么特别的考虑吗?

    作者回复: 想得细致。并没有特别考虑。这个课程的特点是逐步演化,开头只是个胚胎,不断重构发育,最后一步步变成Spring的样子,所以后面的程序跟前面的都会有变化的,稍安勿躁,你一点点看到最后。我希望带给大家的是Spring这个框架的变化定型的过程,而不是一开头就讲现在的Spring是什么样子。

    2023-03-15归属地:浙江
    2
    5
  • Unknown
    getClass().getClassLoader().getResource(filepath) 类加载器获取资源时 此处的filepath 需要放在resource目录里面(手动创建并标识类型为Resource root)

    作者回复: 对的对的。你从Github上的ioc分支可以看到。

    2023-03-15归属地:福建
    3
    5
  • C.
    ioc容器5天的版本手敲的,对应章节的代码:https://github.com/caozhenyuan/mini-spring.git 点击分支查看对应章节的代码。帮大家跟敲不迷路。

    作者回复: 善事。记得给出原始出处。

    2023-03-24归属地:江苏
    2
    3
  • 马儿
    以前的spring的源码都是散的,希望能通过这个课把这些只是串联起来。希望老师讲的时候可以讲一些设计模式,把创建类所在的包也希望能够说明一下,这样的话更方便大家学习了解类的用途和作用。

    作者回复: 完整源码参见 https://github.com/YaleGuo/Minis。按照编辑的意见,在文稿中列出的代码是关键代码,不完整。这一部分可以看Github上的ioc分支。 后面会讲到设计模式,有好几位提到这个建议。

    2023-03-13归属地:四川
    3
收起评论
显示
设置
留言
68
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部