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

05|实现完整的IoC容器:构建工厂体系并添加容器事件

你好,我是郭屹。
前面我们已经实现了 IoC 的核心部分,骨架已经有了,那怎么让这个 IoC 丰满起来呢?这就需要实现更多的功能,让我们的 IoC 更加完备。所以这节课我们将通过建立 BeanFactory 体系,添加容器事件等一系列操作,进一步完善 IoC 的功能。

实现一个完整的 IoC 容器

为了让我们的 MiniSpring 更加专业一点,也更像 Spring 一点,我们将实现 3 个功能点。
进一步增强扩展性,新增 4 个接口。
ListableBeanFactory
ConfigurableBeanFactory
ConfigurableListableBeanFactory
EnvironmentCapable
实现 DefaultListableBeanFactory,该类就是 Spring IoC 的引擎。
改造 ApplicationContext。
下面我们就一条条来看。

增强扩展性

首先我们来增强 BeanFactory 的扩展性,使它具有不同的特性。
我们以前定义的 AutowireCapableBeanFactory 就是在通用的 BeanFactory 的基础上添加了 Autowired 注解特性。比如可以将 Factory 内部管理的 Bean 作为一个集合来对待,获取 Bean 的数量,得到所有 Bean 的名字,按照某个类型获取 Bean 列表等等。这个特性就定义在 ListableBeanFactory 中。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入讲解了如何构建一个完整的IoC容器,通过实现ApplicationContext接口和AbstractApplicationContext抽象类,丰富了IoC容器的功能。文章首先介绍了如何增强扩展性,通过新增接口ListableBeanFactory、ConfigurableBeanFactory、ConfigurableListableBeanFactory和EnvironmentCapable来使BeanFactory具有不同的特性,并且讲解了接口隔离原则在Spring框架中的应用。其次,详细讲解了环境因素的增加,包括PropertyResolver、EnvironmentCapable和Environment接口的实现。接着,展示了IoC引擎DefaultListableBeanFactory的实现,以及事件的发布与监听机制的完善,包括ApplicationEvent、ApplicationListener、ApplicationEventPublisher和ContextRefreshEvent的实现。通过实现ClassPathXmlApplicationContext类,演示了如何将其融入到ApplicationContext框架中。最后,总结了IoC容器的功能包括识别Bean定义、依赖注入、BeanFactory体系和容器应用上下文和事件发布。整体来看,本文对于想要深入理解IoC容器实现原理的读者具有很高的参考价值。

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

全部留言(19)

  • 最新
  • 精选
  • KernelStone
    这一小结其实新增的内容不算多!只是对之前已有的代码进行结构调整。在项目中对DefaultListableBeanFactory生成UML结构图,再进行从上到下的梳理,这样会舒服一些。 0、【接口】BF,Bean工厂 1、【接口】SingletonBeanRegistry,单例Bean仓库 2、DefaultSingletonBeanRegistry,单例Bean仓库默认实现。提供了 1 注册列表 2 单例容器 3 依赖注入管理信息(两个Map,应该是依赖 & 被依赖) 3、【接口】BeanDefinitionRegistry【接口】ListableBF,这两个对照看差异。前者强调对BeanDefinition进行操作,后者强调是对List集合进行操作。 4、【接口】ConfigurableBF,Bean处理器(add & get,没有apply),以及管理依赖信息。 5、【接口】AutowireCapableBF,提供自动装配选项(No、byName、byType),并在初始化前后应用(apply)Bean处理器。 6、【集成接口】ConfigurableListableBF,无内容。 7、【抽象类】AbstractBF,主要是refresh(),invokeInitMethod(),createBean(),构造器注入和属性注入。 8、AbstractAutowireCapableBF,提供成员List<BeanPostProcessor>!也因此它可以通过该成员进行更多的bean处理器操作,即add、get、apply在此有了具体实现。 9、DefaultListableBF,其实没有啥,打开一看只Override了【接口】ListableBF中的4个方法,其余是默认继承。(即沿着类结构往上一堆,上面也说过了) 因此,这节课真没什么新东西,不过梳理这个新的工厂体系,倒是很麻烦。。

    作者回复: 你这个总结真好!

    2023-06-02归属地:广东
    6
  • 马儿
    请教老师一下, 1.ClassPathXmlApplicationContext和AbstractApplicationContext都有beanFactoryPostProcessors属性,是不是重复了呢?感觉直接复用父类的这个属性和相关方法也是可以的。 2.AbstractAutowireCapableBeanFactory这个类中的beanPostProcessors属性写死了是AutowiredAnnotationBeanPostProcessor,不符合面向接口编程的风格。另外由于没有面向BeanPostProcessor导致DefaultListableBeanFactory需要再实现一遍 SingletonBeanRegistry 3.AbstractBeanFactory实现了BeanFactory又写了两个抽象方法applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorAfterInitialization,这里为什么不直接实现AutowireCapableBeanFactory呢?

    作者回复: 你很用心。 1,是重复了。 2,程序最后变成了BeanPostProcessor接口,你接着看。 3,后面有个beanfatory的继承关系图,你可以看看。

    2023-03-23归属地:四川
    3
    3
  • CSY.
    老师我有个问题 ConfigurableBeanFactory 中的 dependentBeanMap 等几个方法为什么要使用同级继承在DefaultSingletonBeanRegistry实现,而不在AbstractBeanFactory等中实现?

    作者回复: 并没有特别的理由,就是参考的Spring的做法。

    2023-04-07归属地:河南
    1
  • 啊良梓是我
    BeanDefinition mbd = this.getBeanDefinition(beanName); Class classToMatch = mbd.getClass(); 这里为什么是拿BeanDefinition的Class的?这样子没意义吧?或者我漏掉什么了? 前面存储Bean class 是 BeanDefinition的BeanName 才对.

    作者回复: 你再仔细看代码,这个class代表的是哪个?

    2023-04-03归属地:广东
    7
    1
  • Geek_513706
    老师,想提个建议,以后添加代码的时候能不能把添加到哪个包里面说清楚

    作者回复: 这个建议已经接纳了,后面的文稿都带上了。完整代码要看Github上的。

    2023-03-28归属地:内蒙古
    1
  • 风轻扬
    思考题:Spring的bean作用域默认是单例的,就是我们的DefaultSingletonBeanRegistry类中持有的那个那个singletons的ConcurrentHashMap,每次获取bean之前,都会先从这个单例map中获取,获取不到才创建。 如果是多线程场景,有竞态条件存在的情况下,可以考虑将bean的作用域改为Prototype类型,对于Prototype类型的bean,Spring会为每次get请求都新建bean,所以每个请求获取到的bean是不一样的,这样就没有并发问题了 除了这两种作用域,还有另外四种作用域,我没怎么接触过,看了一下官方文档了解了一下。 文档地址:https://docs.spring.io/spring-framework/docs/5.3.27-SNAPSHOT/reference/html/core.html#beans-factory-scopes 遇到Spring的问题,可以多看看他们的文档,比搜索引擎强多了,写的很清晰 另外,我有一个问题,请教一下老师,ClassPathXmlApplicationContext为啥要实现BeanFactory?感觉他们两个不是一个体系里的吧,一个是上下文,一个是bean工厂

    作者回复: 实现BeanFActory接口的原因是为了对外提供同样的API。

    2023-03-24归属地:北京
    1
  • Geek_03c08d
    BeanPostProcessor 接口 的 setFactory好像没有什么用

    作者回复: 应该说是MiniSpring没有用到,写在这里,是为了软件的完整性。

    2024-02-28归属地:广东
  • Geek_03c08d
    希望老师回答 1. AbstractAutowireCapableBeanFactory 为什么不加一个继承AutowireCapableBeanFactory,这样就不用写抽象方法了 2. AbstractAutowireCapableBeanFactory 为什么是抽象的? 好像所有的功能都实现了

    作者回复: 其实各种写法都可以,我这么做,主要是跟Spring本身保持一致。

    2024-02-28归属地:广东
  • Cornicione.
    ide一直提示DefaultListableBeanFactory没有实现ConfigurableBeanFactory的部分methods。看了github上的代码也是一样的问题。github上的源码ioc5真的是可以运行的吗?

    作者回复: 刚才又从github上拿下来跑了一下,是没有问题的

    2024-01-17归属地:美国
  • 怕什么,抱紧我
    ConfigurableBeanFactory定义了getDependentBeans()方法; ConfigurableBeanFactory的实现类是DefaultListableBeanFactory,但是 DefaultListableBeanFactory没有实现getDependentBeans()方法,居然没有报错! 要是极客时间能发图,我肯定发一个图上来! 我到底错哪儿了!

    作者回复: 看一下DefaultSingletonBeanRegistry

    2023-05-30归属地:中国香港
收起评论
显示
设置
留言
19
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部