当前位置: 首页 > news >正文

设计模式实战:自定义SpringIOC(理论分析)

自定义SpringIOC(理论分析)

上一篇:设计模式开源实战:观察者模式不知道怎么用?手撕Spring源码中跟着大佬学编程

上一篇我们研究了大佬在Spring源码中使用的观察者模式,今天我们再来聊聊Spring的核心功能——Sping IOC容器,最终我们跟着大佬的思路实现一个属于自己的IOC容器!Start Go!

Spring IOC核心组件

1) BeanFactory

BeanFactory作为最顶层的一个接口,定义了IoC容器的基本功能规范。
在这里插入图片描述
从类图中我们可以发现最终的默认实现类是DefaultListableBeanFactory,它实现了所有的接口。那么为何要定义这么多层次的接口呢?
每个接口都有它的使用场合,主要是为了区分在 Spring 内部操作过程中对象的传递和转化,对对象的数据访问所做的限制。

例如,

  • ListableBeanFactory接口表示这些 Bean 可列表化。
  • HierarchicalBeanFactory表示这些 Bean 是有继承关系的,也就是每个 Bean 可能有父 Bean
  • AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则。

这三个接口共同定义了 Bean 的集合、Bean 之间的关系及 Bean 行为。

在 BeanFactory 里只对 IOC 容器的基本行为做了定义,根本不关心你的 Bean 是如何定义及怎样加载的。正如我们只关心能从工厂里得到什么产品,不关心工厂是怎么生产这些产品的。

2 ) ApplicationContext

BeanFactory 有一个很重要的子接口,就是 ApplicationContext 接口,该接口主要来规范容器中的 bean 对象是非延时加载,即在创建容器对象的时候就对象 bean 进行初始化,并存储到一个容器中。

//延时加载
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("bean.xml"));//立即加载
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
User user = context.getBean("user", User.class);

ApplicationContext 的子类主要包含两个方面:

  • ConfigurableApplicationContext 表示该 Context 是可修改的,也就是在构建 Context 中用户可以动态添加或修改已有的配置信息

  • WebApplicationContext 顾名思义,就是为 web 准备的 Context 他可以直接访问到 ServletContext,通常情况下,这个接口使用少

要知道工厂是如何产生对象的,我们需要看具体的 IOC 容器的实现,Spring 提供了许多 IOC 容器实现,比如:

  • ClasspathXmlApplicationContext : 根据类路径加载 xml 配置文件,并创建 IOC 容器对象。
  • FileSystemXmlApplicationContext :根据系统路径加载 xml 配置文件,并创建 IOC 容器对象。
  • AnnotationConfigApplicationContext :加载注解类配置,并创建 IOC 容器。

在这里插入图片描述
总体来说 ApplicationContext 必须要完成以下几件事。

  • 标识一个应用环境
  • 利用 BeanFactory 创建 Bean 对象
  • 保存对象关系表
  • 能够捕获各种事件

3) Bean定义:BeanDefinition

这里的 BeanDefinition 就是我们所说的 Spring 的 Bean,我们自己定义的各个 Bean 其实会转换成一个个 BeanDefinition 存在于 Spring 的 BeanFactory 中。

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactoryimplements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {//DefaultListableBeanFactory 中使用 Map 结构保存所有的 BeanDefinition 信息private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); 
}   

BeanDefinition 中保存了我们的 Bean 信息,比如这个 Bean 指向的是哪个类、是否是单例的、是否懒加载、这个 Bean 依赖了哪些 Bean 等等。

4) BeanDefinitionReader

Bean 解析过程非常复杂,功能被分得很细,因为这里需要被扩展的地方很多,必须保证足够的灵活性,以应对可能的变化。Bean的解析主要就是对 Spring 配置文件的解析。

这个解析过程主要通过 BeanDefinitionReader 来完成,看看 Spring 中 BeanDefinitionReader 的类结构图,如下图所示。
在这里插入图片描述
BeanDefinitionReader 接口定义的功能

public interface BeanDefinitionReader {/*下面的loadBeanDefinitions都是加载bean定义,从指定的资源中*/int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException;int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;
}

5) BeanFactory后置处理器

后置处理器是一种拓展机制,贯穿Spring Bean的生命周期

后置处理器分为两类:

BeanFactory后置处理器:BeanFactoryPostProcessor

实现该接口,可以在spring的bean创建之前,修改bean的定义属性
在这里插入图片描述

public interface BeanFactoryPostProcessor {/**  该接口只有一个方法postProcessBeanFactory,方法参数是ConfigurableListableBeanFactory,通过该参数,可以获取BeanDefinition*/void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

6) Bean后置处理器:BeanPostProcessor

BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口

实现该接口,可以在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些处理逻辑
在这里插入图片描述

public interface BeanPostProcessor {//bean初始化方法调用前被调用Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;//bean初始化方法调用后被调用Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

IOC流程图

在这里插入图片描述

  1. 容器环境的初始化(系统、JVM 、解析器、类加载器等等)
  2. Bean 工厂的初始化( IOC 容器首先会销毁旧工厂,旧 Bean 、创建新的工厂)
  3. 读取:通过 BeanDefinitonReader 读取我们项目中的配置(application.xml)
  4. 定义:通过解析 xml 文件内容,将里面的 Bean 解析成 BeanDefinition(未实例化、未初始化)
  5. 将解析得到的 BeanDefinition ,存储到工厂类的Map容器中
  6. 调用 BeanFactoryPostProcessor 该方法是一种功能增强,可以在这个步骤对已经完成初始化的 BeanFactory 进行属性覆盖,或是修改已经注册到 BeanFactory 的 BeanDefinition
  7. 通过反射实例化 bean 对象
  8. 进入到 Bean 实例化流程,首先设置对象属性
  9. 检查 Aware 相关接口,并设置相关依赖
  10. 前置处理器,执行 BeanPostProcesser 的before 方法对 bean 进行扩展
  11. 检查是否有实现 initializingBean 回调接口,如果实现就要回调其中的 AftpropertiesSet() 方法,(通过可以完成一些配置的加载)
  12. 检查是否有配置自定义的 init-method ,
  13. 后置处理器执行 BeanPostProcesser 的after 方法 --> AOP 就是在这个阶段完成的, 在这里判断 bean 对象是否实现接口,实现就使用 JDK 代理,否则选择 CGLIB
  14. 对象创建完成,添加到BeanFactory的单例池中。

往期回顾

设计模式开源实战:观察者模式不知道怎么用?手撕Spring源码中跟着大佬学编程

设计模式开源实战:大佬是怎么使用工厂模式的?来看看Spring中工厂模式的应用就知道了

http://www.lryc.cn/news/602578.html

相关文章:

  • 中国汽车能源消耗量(2010-2024年)
  • 力扣17:电话号码的字母组合
  • 设计模式(二十四)行为型:访问者模式详解
  • ADB+Python控制(有线/无线) Scrcpy+按键映射(推荐)
  • 【学习笔记】AD7708/18(1)-理解官网的参考代码
  • MacBook IOS操作系统格式化U盘FAT32
  • 【深度解析】R语言与作物模型(以DSSAT模型为例)融合应用
  • 分布式微服务--核心组件与架构关系(一)
  • R语言简介(附电子书资料)
  • Leetcode_349.两个数组的交集
  • JavaScript手录09-内置对象【String对象】
  • 6.2 总线事务和定时 (答案见原书 P295)
  • 基于Flask的智能停车场管理系统开发实践
  • C语言:20250728学习(指针)
  • 使用node-cron实现Node.js定时任务
  • Javaweb Day3
  • 主要分布于内侧内嗅皮层的层Ⅲ的网格-速度联合细胞(Grid × Speed Conjunctive Cells)对NLP中的深层语义分析的积极影响和启示
  • 学习人工智能所需知识体系及路径详解
  • BUUCTF-MISC-[HBNIS2018]caesar1
  • 科技风杂志《科技风》杂志社科技风编辑部2025年第19期目录
  • 《Ai智能眼镜的市场定义及用户分析》- 深圳市天趣星空科技有限公司 CEO 王洁
  • 【7.26-7.28胜算云AI日报:首个开源3D世界生成模型腾讯混元、微软预示 8 月 GPT-5 发布、Nemotron推理、商汤悟能、DM夺金】
  • Python 实现多服务器并发启动 SDK-C Master 与 Viewer 的分布式方案
  • 科技赋能成长 脑力启迪未来
  • windows内核研究(异常-CPU异常记录)
  • 计算机视觉---Halcon概览
  • 暑期自学嵌入式——Day10(C语言阶段)
  • 生成器和迭代器的区别
  • 【65 Pandas+Pyecharts | 山东省2025年高考志愿投档数据分析可视化】
  • MCP架构:模型上下文协议的范式革命与工程实践