0

0

理解控制反转 (IoC)_面向对象在现代框架中的演进

P粉602998670

P粉602998670

发布时间:2026-02-18 13:03:10

|

116人浏览过

|

来源于php中文网

原创

ioc 的本质是“谁决定对象怎么创建”,即对象的创建时机和依赖来源是否由自身决定;若a类构造函数接收b实例而非直接new b(),则控制权移交,实现反转。

理解控制反转 (ioc)_面向对象在现代框架中的演进

IoC 不是“把控制权交给框架”,而是“谁决定对象怎么创建”

很多人一说控制反转,就想到 Spring 的 @Autowired 或依赖注入容器,以为“框架接管了 new”。其实核心判断只有一条:对象的创建时机和依赖来源,是否由该对象自身决定?如果 A 类里直接 new B(),那 A 控制着 B 的实例化;如果 A 的构造函数接收一个 B 实例(不管是谁传进来的),控制权就移交出去了——这就是反转的实质。

常见错误现象:NullPointerException@Autowired 字段上爆发,但类明明被扫描到了。原因往往是手动 new A(),绕过了容器生命周期,导致注入字段仍是 null

  • 使用场景:单元测试中需替换真实依赖(如用 MockB 替代 RealB),必须通过构造/设值注入,不能硬编码 new
  • 参数差异:构造注入强制依赖不为空,设值注入允许可选依赖,但容易遗漏初始化
  • 性能影响:容器启动时需解析依赖图并实例化,冷启动稍慢;运行时对象创建开销反而更低(复用已有实例)

手写简易 IoC 容器的关键三步

不用 Spring 也能理解 IoC:本质是“注册 → 解析 → 创建”。重点不在功能多,而在明确控制流从哪断开。

常见错误现象:自己写的工厂方法里仍用 if-else 判断类型再 new,只是把 new 搬了个地方,没真正反转。

v0.dev
v0.dev

Vercel推出的AI生成式UI工具,通过文本描述生成UI组件代码

下载
  • 注册:用 Map<class>, Object></class> 存单例,或 Map<class>, Class>></class> 存类型映射(如 put(B.class, MockB.class)
  • 解析:递归扫描构造函数参数类型,查注册表,缺哪个就先创建哪个(注意循环依赖:A 依赖 BB 又依赖 A
  • 创建:用 Constructor.newInstance(),别用 new —— 这才是把控制权交出去的动作

Spring 中 @Bean@Component 的区别不是“能不能用”,而是“谁在管理生命周期”

@Component 是让 Spring 扫描到后自动注册为 Bean;@Bean 是你在配置类里显式告诉 Spring:“这个对象归你管”。两者最终都进入同一个容器,但入口不同。

常见错误现象:在 @Configuration 类里写 new MyService() 并返回,以为加了 @Bean 就进了容器——错。Spring 只代理 @Bean 方法的调用,不拦截方法体内的 new 行为。

  • 使用场景:@Component 适合业务组件(ServiceRepository);@Bean 适合第三方类(如 RestTemplateDataSource)或需要复杂初始化逻辑的对象
  • 兼容性影响:用 @Bean 声明的 Bean 默认是单例,但可以加 @Scope("prototype")@Component 同理,但语义上更倾向无状态组件
  • 容易踩的坑:在 @Bean 方法里调用本类另一个 @Bean 方法(如 service() 调用 dao()),会绕过代理,导致两次创建——应改为注入 Dao 字段再用

IoC 的代价:调试时看不到对象从哪来,堆栈里全是 ReflectiveConstructorAccessor

当一个 NullPointerException 出现在某字段上,你得倒推:它是不是被容器注入的?注入源是 @Bean 方法还是 @Component?有没有被 @Profile 过滤掉?这些信息都不在代码行里,而在配置和注解组合中。

最常被忽略的点:IDE 跳转不到注入点。Ctrl+Click myService 字段,看到的是接口或抽象类,实际实现类可能分布在多个模块、多个 @Bean 方法、甚至条件化配置里。这时候得靠 ApplicationContext.getBeanNamesForType(MyService.class) 查到底注册了几个、哪个生效。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

142

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

81

2026.01.26

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

244

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

766

2024.03.01

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

817

2023.08.22

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

57

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

60

2025.11.27

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1508

2023.10.19

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

561

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号