Spring IOC(Inversion of Control,控制反转)是Spring框架的核心,它将对象的创建和依赖关系的管理从程序代码中转移到容器中。下面详细介绍其原理,并通过流程图和UML类图进行展示。
一、IOC与DI概念
- IOC(控制反转):传统方式下,对象自己负责依赖对象的创建;IOC则将这一职责反转给容器,对象只需声明依赖,由容器在运行时注入。
- DI(依赖注入):IOC的实现方式,容器通过构造函数、setter方法或字段注入将依赖对象传递给目标对象。
二、Spring IOC容器的工作原理
Spring IOC容器主要基于BeanFactory和ApplicationContext接口,其核心工作流程如下:
整个过程通过一系列内部组件协作完成,核心组件包括:
- BeanFactory:IOC容器的顶层接口,提供基本的getBean()方法。
- ApplicationContext:扩展了BeanFactory,增加了国际化、事件传播等功能。
- BeanDefinition:描述Bean的元数据,包括类名、作用域、依赖、初始化方法等。
- BeanPostProcessor:在Bean初始化前后提供扩展点,用于AOP等功能的实现。
- BeanFactoryPostProcessor:允许在Bean定义加载后、实例化前修改Bean定义。
| BeanDefinition | 描述一个 Bean 的定义信息,包括类名、作用域、属性、构造函数参数、依赖等。 |
| BeanDefinitionRegistry | 注册 BeanDefinition 的接口,如 DefaultListableBeanFactory 实现了它。 |
| BeanFactory | 获取 Bean 的根接口,提供 getBean() 等方法。 |
| DefaultListableBeanFactory | 最常用的 BeanFactory 实现,也是 ApplicationContext 内部持有的容器。 |
| BeanDefinitionReader | 读取配置资源(如 XML、注解)并解析为 BeanDefinition,然后注册到 BeanDefinitionRegistry。 |
| BeanPostProcessor | Bean 后置处理器,可在 Bean 初始化前后执行自定义逻辑。 |
| BeanFactoryPostProcessor | 容器级后置处理器,可在 BeanDefinition 加载后、Bean 实例化前修改 BeanDefinition。 |
三、流程图展示
以下流程图描述了Spring IOC容器初始化和Bean创建的主要步骤:
#mermaid-svg-GtJcF7C31foT0uvL{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GtJcF7C31foT0uvL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GtJcF7C31foT0uvL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GtJcF7C31foT0uvL .error-icon{fill:#552222;}#mermaid-svg-GtJcF7C31foT0uvL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GtJcF7C31foT0uvL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GtJcF7C31foT0uvL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GtJcF7C31foT0uvL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GtJcF7C31foT0uvL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GtJcF7C31foT0uvL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GtJcF7C31foT0uvL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GtJcF7C31foT0uvL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GtJcF7C31foT0uvL .marker.cross{stroke:#333333;}#mermaid-svg-GtJcF7C31foT0uvL svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GtJcF7C31foT0uvL p{margin:0;}#mermaid-svg-GtJcF7C31foT0uvL .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-GtJcF7C31foT0uvL .cluster-label text{fill:#333;}#mermaid-svg-GtJcF7C31foT0uvL .cluster-label span{color:#333;}#mermaid-svg-GtJcF7C31foT0uvL .cluster-label span p{background-color:transparent;}#mermaid-svg-GtJcF7C31foT0uvL .label text,#mermaid-svg-GtJcF7C31foT0uvL span{fill:#333;color:#333;}#mermaid-svg-GtJcF7C31foT0uvL .node rect,#mermaid-svg-GtJcF7C31foT0uvL .node circle,#mermaid-svg-GtJcF7C31foT0uvL .node ellipse,#mermaid-svg-GtJcF7C31foT0uvL .node polygon,#mermaid-svg-GtJcF7C31foT0uvL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GtJcF7C31foT0uvL .rough-node .label text,#mermaid-svg-GtJcF7C31foT0uvL .node .label text,#mermaid-svg-GtJcF7C31foT0uvL .image-shape .label,#mermaid-svg-GtJcF7C31foT0uvL .icon-shape .label{text-anchor:middle;}#mermaid-svg-GtJcF7C31foT0uvL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GtJcF7C31foT0uvL .rough-node .label,#mermaid-svg-GtJcF7C31foT0uvL .node .label,#mermaid-svg-GtJcF7C31foT0uvL .image-shape .label,#mermaid-svg-GtJcF7C31foT0uvL .icon-shape .label{text-align:center;}#mermaid-svg-GtJcF7C31foT0uvL .node.clickable{cursor:pointer;}#mermaid-svg-GtJcF7C31foT0uvL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GtJcF7C31foT0uvL .arrowheadPath{fill:#333333;}#mermaid-svg-GtJcF7C31foT0uvL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GtJcF7C31foT0uvL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GtJcF7C31foT0uvL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GtJcF7C31foT0uvL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GtJcF7C31foT0uvL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GtJcF7C31foT0uvL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GtJcF7C31foT0uvL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GtJcF7C31foT0uvL .cluster text{fill:#333;}#mermaid-svg-GtJcF7C31foT0uvL .cluster span{color:#333;}#mermaid-svg-GtJcF7C31foT0uvL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GtJcF7C31foT0uvL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GtJcF7C31foT0uvL rect.text{fill:none;stroke-width:0;}#mermaid-svg-GtJcF7C31foT0uvL .icon-shape,#mermaid-svg-GtJcF7C31foT0uvL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GtJcF7C31foT0uvL .icon-shape p,#mermaid-svg-GtJcF7C31foT0uvL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GtJcF7C31foT0uvL .icon-shape rect,#mermaid-svg-GtJcF7C31foT0uvL .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GtJcF7C31foT0uvL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GtJcF7C31foT0uvL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GtJcF7C31foT0uvL :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
是
否
开始
加载配置(XML/注解/Java Config)
解析配置为BeanDefinition
注册BeanDefinition到容器
调用BeanFactoryPostProcessor(可选)
遍历所有BeanDefinition
Bean是否单例?
实例化Bean(反射/CGLIB)
原型Bean: 每次请求时创建
属性填充(依赖注入)
执行BeanPostProcessor前置处理
执行初始化方法(init-method等)
执行BeanPostProcessor后置处理
注册销毁回调(单例)
将Bean放入缓存(单例)
返回完整Bean实例
是否还有未处理的Bean?
容器启动完成
等待getBean请求
从缓存或新创建返回Bean
容器关闭时销毁单例Bean
结束
四、核心接口类图展示
Spring IOC核心接口的类图:
#mermaid-svg-JOR4wlxehufhfoTD{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-JOR4wlxehufhfoTD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JOR4wlxehufhfoTD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JOR4wlxehufhfoTD .error-icon{fill:#552222;}#mermaid-svg-JOR4wlxehufhfoTD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JOR4wlxehufhfoTD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JOR4wlxehufhfoTD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JOR4wlxehufhfoTD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JOR4wlxehufhfoTD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JOR4wlxehufhfoTD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JOR4wlxehufhfoTD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JOR4wlxehufhfoTD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JOR4wlxehufhfoTD .marker.cross{stroke:#333333;}#mermaid-svg-JOR4wlxehufhfoTD svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JOR4wlxehufhfoTD p{margin:0;}#mermaid-svg-JOR4wlxehufhfoTD g.classGroup text{fill:#9370DB;stroke:none;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-JOR4wlxehufhfoTD g.classGroup text .title{font-weight:bolder;}#mermaid-svg-JOR4wlxehufhfoTD .nodeLabel,#mermaid-svg-JOR4wlxehufhfoTD .edgeLabel{color:#131300;}#mermaid-svg-JOR4wlxehufhfoTD .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-JOR4wlxehufhfoTD .label text{fill:#131300;}#mermaid-svg-JOR4wlxehufhfoTD .labelBkg{background:#ECECFF;}#mermaid-svg-JOR4wlxehufhfoTD .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-JOR4wlxehufhfoTD .classTitle{font-weight:bolder;}#mermaid-svg-JOR4wlxehufhfoTD .node rect,#mermaid-svg-JOR4wlxehufhfoTD .node circle,#mermaid-svg-JOR4wlxehufhfoTD .node ellipse,#mermaid-svg-JOR4wlxehufhfoTD .node polygon,#mermaid-svg-JOR4wlxehufhfoTD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JOR4wlxehufhfoTD .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-JOR4wlxehufhfoTD g.clickable{cursor:pointer;}#mermaid-svg-JOR4wlxehufhfoTD g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-JOR4wlxehufhfoTD g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-JOR4wlxehufhfoTD .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-JOR4wlxehufhfoTD .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-JOR4wlxehufhfoTD .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-JOR4wlxehufhfoTD .dashed-line{stroke-dasharray:3;}#mermaid-svg-JOR4wlxehufhfoTD .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-JOR4wlxehufhfoTD #compositionStart,#mermaid-svg-JOR4wlxehufhfoTD .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JOR4wlxehufhfoTD #compositionEnd,#mermaid-svg-JOR4wlxehufhfoTD .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JOR4wlxehufhfoTD #dependencyStart,#mermaid-svg-JOR4wlxehufhfoTD .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JOR4wlxehufhfoTD #dependencyStart,#mermaid-svg-JOR4wlxehufhfoTD .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JOR4wlxehufhfoTD #extensionStart,#mermaid-svg-JOR4wlxehufhfoTD .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JOR4wlxehufhfoTD #extensionEnd,#mermaid-svg-JOR4wlxehufhfoTD .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JOR4wlxehufhfoTD #aggregationStart,#mermaid-svg-JOR4wlxehufhfoTD .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JOR4wlxehufhfoTD #aggregationEnd,#mermaid-svg-JOR4wlxehufhfoTD .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JOR4wlxehufhfoTD #lollipopStart,#mermaid-svg-JOR4wlxehufhfoTD .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JOR4wlxehufhfoTD #lollipopEnd,#mermaid-svg-JOR4wlxehufhfoTD .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-JOR4wlxehufhfoTD .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-JOR4wlxehufhfoTD .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JOR4wlxehufhfoTD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JOR4wlxehufhfoTD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JOR4wlxehufhfoTD :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
注册/管理
使用
使用
«interface»
BeanFactory
+getBean(String) : Object
+containsBean(String) : boolean
+isSingleton(String) : boolean
«interface»
ApplicationContext
+getEnvironment() : Environment
+publishEvent(ApplicationEvent)
«interface»
ConfigurableApplicationContext
+refresh() : void
+close() : void
AbstractApplicationContext
#obtainFreshBeanFactory() : ConfigurableListableBeanFactory
#invokeBeanFactoryPostProcessors()
#registerBeanPostProcessors()
#finishBeanFactoryInitialization()
«interface»
BeanDefinitionRegistry
+registerBeanDefinition(String, BeanDefinition)
+removeBeanDefinition(String)
«interface»
BeanDefinition
+getBeanClassName() : String
+getScope() : String
+isSingleton() : boolean
+getPropertyValues() : PropertyValues
«interface»
BeanPostProcessor
+postProcessBeforeInitialization(Object, String) : Object
+postProcessAfterInitialization(Object, String) : Object
«interface»
BeanFactoryPostProcessor
+postProcessBeanFactory(ConfigurableListableBeanFactory)
类图说明:
- BeanFactory是最基础的容器接口。
- ApplicationContext继承了BeanFactory,并扩展了更多企业级功能。
- ConfigurableApplicationContext定义了refresh()方法,是容器启动的入口。
- AbstractApplicationContext是模板实现,实现了refresh()方法的具体步骤。
- BeanDefinitionRegistry负责管理Bean定义。
- BeanDefinition封装Bean的元数据。
- BeanPostProcessor和BeanFactoryPostProcessor提供了扩展点。
五、总结
Spring IOC的核心原理可以概括为:通过反射技术,根据配置信息动态创建对象并管理它们之间的依赖关系。它将对象生命周期管理从代码中解耦,提高了系统的可维护性和可测试性。理解IOC的原理对于深入使用Spring框架、排查问题以及进行二次开发都至关重要。


