Spring IOC 容器深度解析
Spring IOC
一、基础介绍
什么是 IOC
IOC:Inversion Of Control,即控制反转,是一种设计思想。在传统的 Java SE 程序设计中,我们直接在对象内部通过 new 的方式来创建对象,是程序主动创建依赖对象而在 Spring 程序设计中,IOC 是有专门的容器去控制对象。所谓控制就是对象的创建、初始化、销毁。
创建对象: 原来是 new 一个,现在是由 Spring 容器创建。
初始化对象: 原来是对象自己通过构造器或者 setter 方法给依赖的对象赋值,现在是由 Spring 容器自动注入。
销毁对象: 原来是直接给对象赋值 null 或做一些销毁操作,现在是 Spring 容器管理生命周期负责销毁对象。
控制反转的含义
IOC 解决了繁琐的对象生命周期的操作,解耦了我们的代码。所谓反转:其实是反转的控制权,前面提到是由 Spring 来控制对象的生命周期,那么对象的控制就完全脱离了我们的控制,控制权交给了 Spring 。这个反转是指:我们由对象的控制者变成了 IOC 的被动控制者。
依赖注入(DI)
依赖注入(DI)是实现这种技术的一种方式。传统开发过程中,我们需要通过 new 关键字来创建对象。使用 IoC 思想开发方式的话,我们不通过 new 关键字创建对象,而是通过 IoC 容器来帮我们实例化对象。
通过 IoC 的方式,可以大大降低对象之间的耦合度。
二、底层原理
核心机制
Spring IOC 的底层核心是 反射 + 工厂模式。容器在启动时解析配置或注解,将 Bean 封装为 BeanDefinition 注册到容器中。在 Bean 创建阶段,Spring 通过反射实例化对象,并在属性填充阶段完成依赖注入。整个过程由 BeanFactory 统一管理,而 ApplicationContext 在此基础上扩展了事件、AOP、国际化等企业级能力,实现了真正的控制反转。
ApplicationContext 容器
通过 ApplicationContext 这个 IoC 容器的入口,用它的两个具体的实现子类,从 class path 或者 file path 中读取数据,用 getBean() 获取具体的 bean instance。
ApplicationContext 的里面有两个具体的实现子类,用来读取配置配件的:
ClassPathXmlApplicationContext: 从 class path 中加载配置文件,更常用一些。
FileSystemXmlApplicationContext: 从本地文件中加载配置文件,不是很常用,如果再到 Linux 环境中,还要改路径,不是很方便。
不过现在用的比较少了,现代 Spring 更多使用 AnnotationConfigApplicationContext。
容器初始化流程
首先初始化 Spring IoC 容器, new 一个 AnnotationConfigApplicationContext 类,底层会先注册配置类为 BeanDefinition,然后再调用 AbstractApplicationContext.refresh()。
在 refresh 过程中,Spring 创建并初始化 BeanFactory,加载并解析 BeanDefinition(解析注解或 XML 配置),注册各种 BeanPostProcessor 用于增强对象(如创建 AOP 代理)扩展点。
在容器刷新后期,ApplicationContext 会遍历所有 BeanDefinition,根据其元数据(scope、lazy-init 等)决定是否进行单例 Bean 的预实例化,并通过调用 getBean() 触发 Bean 的创建。Bean 创建过程中,Spring 根据 BeanDefinition 中的配置,通过反射实例化对象,在 populateBean 阶段完成依赖注入,随后在初始化阶段通过 BeanPostProcessor 对 Bean 进行增强,例如生成 AOP 代理,最终将完整的 Bean 放入单例缓存中供后续使用。