【Spring进阶】Spring IOC实现原理是什么?容器创建和对象创建的时机是什么?

【Spring进阶】Spring IOC实现原理是什么?容器创建和对象创建的时机是什么?



👨‍💻程序员三明治个人主页
🔥 个人专栏: 《设计模式精解》《重学数据结构》

🤞先做到 再看见!


Bean的生命周期

在这里插入图片描述

1️⃣** 初始化容器**

ApplicationContext ctx =newClassPathXmlApplicationContext("applicationContext.xml");
  • ApplicationContextBeanFactory 的子接口;
  • 它在启动(refresh())时会完成 配置加载 + Bean 注册 + Bean 实例化
  • 这是一个预加载容器(启动即创建 Bean)。

⚠️ 与之相对的 BeanFactory 是延迟加载容器,只有在第一次调用 getBean() 时才会创建对象。

2️⃣** 解析配置并生成 BeanDefinition**

Spring 首先会读取配置文件(如 XML 或注解),解析 <bean> 标签中的定义,例如:

<beanid="myBean"class="com.example.MyBean"scope="singleton"/>

这些信息会被封装成 BeanDefinition 对象,描述 Bean 的元数据,包括:

属性说明
idBean 的唯一名称
classBean 的全类名
scope作用域(singleton / prototype)
constructor args / properties依赖信息

BeanDefinition 不是 Bean 实例,而是告诉容器“如何创建 Bean”的蓝图。


3️⃣** 注册 BeanDefinition**

Spring 将所有的 BeanDefinition 注册到一个全局的注册表中:

Map<String,BeanDefinition> beanDefinitionMap =newConcurrentHashMap<>(); beanDefinitionMap.put("myBean",BeanDefinition@1234);

📘 这一步只完成定义注册,还没有实例化对象。

当容器启动(ApplicationContext)或首次 getBean()BeanFactory)时,Spring 开始真正创建对象。
无论触发方式如何,最终都会进入相同的调用链:

MyBean bean = ctx.getBean("myBean");getBean() └── doGetBean() ├── getSingleton()// 从缓存中查找是否已创建 ├── createBean()// 未创建则进入创建流程 │ ├── createBeanInstance()// 反射实例化对象 │ ├── populateBean()// 依赖注入 │ └── initializeBean()// 初始化回调 └── addSingleton()// 放入缓存池

1️⃣** createBeanInstance():反射创建对象**

Class<?> clazz =Class.forName(beanDefinition.getBeanClassName());Object bean = clazz.getDeclaredConstructor().newInstance();
  • Spring 使用 反射 动态创建 Bean 实例;
  • 这一步只负责实例化,不注入依赖;
  • 对象创建后暂存在缓存中,等待依赖注入。

2️⃣** populateBean():执行依赖注入**

Spring 会根据 BeanDefinition 或注解信息完成依赖注入。
常见的三种方式:

注入方式示例实现方式
构造器注入<constructor-arg>反射调用构造器
Setter 注入<property>反射调用 setter 方法
字段注入@Autowired
/ @Resource
反射直接设置字段值

示例:

@ComponentpublicclassMyBean{@AutowiredprivateMyService myService;}

底层反射逻辑:

Field field = clazz.getDeclaredField("myService"); field.setAccessible(true); field.set(bean, context.getBean("myService"));

3️⃣** initializeBean():初始化与回调**

依赖注入完成后,Spring 会执行初始化回调,包含:

  1. 调用 BeanNameAwareApplicationContextAware 等接口;
  2. 执行 InitializingBean.afterPropertiesSet()
  3. 调用 init-method
  4. 触发 BeanPostProcessor(如 AOP 代理增强)。

4️⃣** addSingleton():放入单例缓存**

当 Bean 完全创建完毕后,Spring 会将其放入一级缓存:

singletonObjects.put(beanName, bean);

这样之后再次 getBean("myBean"),会直接从缓存中取,不再重新创建。

1️⃣ 读取配置文件或扫描注解 ↓ 2️⃣ 生成 BeanDefinition(Bean 蓝图) ↓ 3️⃣ 注册到 beanDefinitionMap(定义注册) ↓ 4️⃣ 调用 getBean() 或 容器启动触发创建 ↓ 5️⃣ createBean() → 反射创建对象 ↓ 6️⃣ populateBean() → 执行依赖注入 ↓ 7️⃣ initializeBean() → 初始化与增强 ↓ 8️⃣ addSingleton() → 缓存单例 Bean ↓ 9️⃣ 返回 Bean 实例 

说说BeanFactory和ApplicantContext?

可以这么形容,BeanFactory是Spring的“心脏”,ApplicantContext是完整的“身躯”。

  • BeanFactory(Bean工厂)是Spring框架的基础设施,面向Spring本身。
  • ApplicantContext(应用上下文)建立在BeanFactoty基础上,面向使用Spring框架的开发者。

Spring为BeanFactory提供了很多种实现,最常用的是XmlBeanFactory,但在Spring3.2中已被废弃,建议使用XmlBeanDefinitionReader、DefaultListableBeanFactory。

BeanFactory接口位于类结构树的顶端,它最主要的方法就是getBean(String var1),这个方法从容器中返回特定名称的Bean。

BeanFactory的功能通过其它的接口得到了不断的扩展,比如AbstractAutowireCapableBeanFactory定义了将容器中的Bean按照某种规则(比如按名字匹配、按类型匹配等)进行自动装配的方法。

这里看一个 XMLBeanFactory(已过期) 获取bean 的例子:

ApplicationContext 接口

ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。可以这么说,使用BeanFactory就是手动档,使用ApplicationContext就是自动档。

ApplicationContext 继承了HierachicalBeanFactory和ListableBeanFactory接口,在此基础上,还通过其他的接口扩展了ApplicationContext的功能,包括:

  • Bean instantiation/wiring
  • Bean 的实例化/串联
  • 自动的 BeanPostProcessor 注册
  • 自动的 BeanFactoryPostProcessor 注册
  • 方便的 MessageSource 访问(i18n)
  • ApplicationEvent 的发布与 BeanFactory 懒加载的方式不同,它是预加载,所以,每一个 bean 都在 ApplicationContext 启动之后实例化

这是 ApplicationContext 的使用例子:

ApplicationContext 包含 BeanFactory 的所有特性,通常推荐使用前者。

如果我的内容对你有帮助,请辛苦动动您的手指为我点赞,评论,收藏。感谢大家!!

在这里插入图片描述


我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=h70g0sv71wz

Read more

Python中秋月圆夜:手把手实现月相可视化,用代码赏千里共婵娟

Python中秋月圆夜:手把手实现月相可视化,用代码赏千里共婵娟

文章目录 * 📖 引言 * 🎯 项目概述 * 🛠️ 技术架构解析 * 项目结构 * 💡 实现思路 * 月相计算核心 * 可视化难点 * 核心模块设计 * `moon_calculator.py` - 核心计算引擎 * 可视化渲染类 * 📊 四种图表实现详解 * 时间轴图表 - 连续月相展示 * 月相曲线图 - 数学规律可视化 * 当前月相图 * 图像Base64编码 * 🌐 HTML界面生成 * `generate_html.py` - 界面组装器 * CSS3特效设计 * JavaScript交互特效 * 🌟 结语 📖 引言 中秋节,这个承载着千年文化的传统节日,以其独特的满月寓意着团圆与和谐。我们不妨用Python这门优雅的编程语言,来创造一个富有诗意的中秋节月相可视化器。本文将带您通过代码的艺术,重现天空中月亮的盈亏变化,并在中秋节这个特殊的日子里,为我们的程序增添一抹传统文化的色彩。 🎯 项目概述 我们将构建一个功能丰富的月相可视

By Ne0inhk
Python异步编程基石:深入理解asyncio核心原理与实战

Python异步编程基石:深入理解asyncio核心原理与实战

摘要 本文深入剖析Python异步编程核心库asyncio的工作原理,从事件循环、协程、Future到Task的完整技术栈。通过真实性能对比数据、企业级案例和5个架构流程图,全面解析async/await底层机制。涵盖异步编程最佳实践、性能优化技巧和故障排查方案,帮助开发者掌握高并发程序设计精髓,提升I/O密集型应用性能数倍。 1 异步编程:为什么它是Python高性能的关键 在我13年的Python开发经验中,异步编程是性能优化的分水岭。记得曾经处理一个需要调用10个外部API的任务,同步版本需要20多秒,而改用异步后仅需2秒——这种10倍性能提升让我彻底认识到异步编程的价值。 1.1 同步 vs 异步:直观对比 想象你在餐厅点餐的场景: * 同步:点完第一个菜后站着等厨师做完,再点第二个菜,效率极低 * 异步:点完所有菜后找座位等待,厨师并行制作,服务员送餐时通知你 这就是异步编程的核心优势:避免不必要的等待,充分利用等待时间执行其他任务。 import time import asyncio # 同步版本:顺序执行,总耗时=各任务耗时之和 def

By Ne0inhk
Python 小工具实战:图片水印批量添加工具

Python 小工具实战:图片水印批量添加工具

Python 小工具实战:图片水印批量添加工具 Python 小工具实战:图片水印批量添加工具,本文详细介绍了使用 Python开发 给图片加水印的工具,该工具基于 Pillow 和 tkinter 库构建,可解决单图处理耗时、专业软件操作复杂的问题。工具支持单图与批量处理,用户能自定义水印文字、字体大小、透明度及颜色,还可选择 9 个常用水印位置或设置行列重复分布。新增的全屏水印模式可通过调整旋转角度与间距,生成铺满图片的版权保护水印,且界面采用卡片式布局,搭配浅灰背景与蓝色按钮,简洁美观,底部状态栏实时显示操作进度。文中提供完整可运行代码,并给出参数校验、字体兼容、常见报错解决等实用内容,新手按步骤即可上手,或者直接运行使用。 前言     Python作为一门简洁、易读、功能强大的编程语言,其基础语法是入门学习的核心。掌握好基础语法,能为后续的编程实践打下坚实的基础。本文将全面讲解Python3的基础语法知识,适合编程初学者系统学习。Python以其简洁优雅的语法和强大的通用性,成为当今最受欢迎的编程语言。本专栏旨在系统性地带你从零基础入门到精通Python核心。无论你是

By Ne0inhk
Python 轻量化环境管理利器 UV 入门与 Windows 下安装实战

Python 轻量化环境管理利器 UV 入门与 Windows 下安装实战

文章目录 * 一、UV是什么?解决什么问题? * 1.1 传统Python环境管理的三大痛点 * 痛点1:多工具碎片化操作,效率低下 * 痛点2:依赖冲突与环境隔离难题 * 痛点3:工具学习成本高,协作壁垒明显 * 1.2 UV如何解决?核心优势解析 * 优势1:一体化设计,命令行极简主义 * 优势2:智能环境管理,冲突预警与自动隔离 * 优势3:轻量化与高性能,适配现代开发节奏 * 优势4:渐进式迁移,兼容现有生态 * 1.3 目标用户与典型场景 * 二、Windows下UV安装实战 * 2.1 前置步骤:安装Visual C++ 2015-2022运行时 * 2.1.1 为什么必须安装? * 2.1.2 安装步骤

By Ne0inhk