2分钟带你理解IOC

IoC与DI详解

1.  IoC是什么

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:

 

谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

用图例说明一下,传统程序设计如图2-1,都是主动去创建相关对象然后再组合起来:

 

图2-1 传统应用程序示意图

当有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了,如图2-2所示:

 

图2-2有IoC/DI容器后程序结构示意图

 

2.  IoC能做什么

IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。

IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

 

3.  IoC和DI

DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

 

理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

 

谁依赖于谁:当然是某个容器管理对象依赖于IoC容器;“被注入对象的对象”依赖于“依赖对象”;

为什么需要依赖:容器管理对象需要IoC容器来提供对象需要的外部资源;

谁注入谁:很明显是IoC容器注入某个对象,也就是注入“依赖对象”;

●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

 

IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。


欢迎大家关注我的公众号:java技术学习之道(javajsxxzd),长期分享各种技术文章。


来源:http://sishuok.com/forum/blogPost/list/2427.html



<think>嗯,用户现在问的是关于IOC理解。之前他们问过AQS和可重入锁,看来他们对Java的并发和框架设计比较感兴趣。现在转向IOC,可能需要从设计模式到具体实现的讲解。 首先,IOC是控制反转,可能用户知道这个概念但不清楚具体实现,比如Spring中的IOC容器。要解释清楚IOC的核心思想,以及和DI的关系。用户可能混淆这些术语,需要区分开来。 用户可能需要了解IOC解决的问题,比如紧耦合的问题,以及如何通过容器管理对象生命周期。要举例说明,比如传统方式new对象和IOC容器注入的区别。 还要考虑用户的实际应用场景,比如在Spring中如何使用注解配置Bean,或者XML配置。可能需要提到常见的注解如@Component、@Autowired,以及容器如何实现依赖注入。 另外,用户可能想知道IOC的好处,比如提高可测试性、降低耦合度,便于扩展和维护。这些实际开发中的优势需要强调。 要注意回答的结构,先讲概念,再讲实现,最后好处和应用。可能用户是准备面试,需要条理清晰,重点突出。需要避免过于技术化的术语,用易懂的例子帮助理解。 还要检查之前的回答是否有使用LaTeX格式,确保数学公式正确,比如状态变化的例子。不过IOC可能不需要数学公式,但可以举例代码片段,比如XML配置或Java配置的例子。 最后总结IOC的重要性,以及在现代框架中的应用,比如Spring的核心机制。确保回答覆盖基本点,同时深入浅出。</think>--- ### **IOC(控制反转)核心理解** $$ \text{传统程序} \xrightarrow{\text{控制反转}} \text{框架管理对象生命周期} $$ --- ### **1. 核心概念** #### **(1) 定义** - **控制反转(Inversion of Control)**:将对象的创建、依赖注入和生命周期管理权从程序员转移给容器 - **数学表达**: $$ \text{传统编程} = \text{Class A} \rightarrow \text{new Class B()} $$ $$ \text{IOC模式} = \text{Container} \rightarrow \text{创建B实例} \rightarrow \text{注入A} $$ #### **(2) 与DI的关系** $$ \text{IOC} \supset \text{DI(依赖注入)} $$ - **DI是IOC的实现方式**:通过构造函数/Setter/接口注入依赖 - **示例代码**: ```java // 传统方式(紧耦合) class UserService { private UserDao dao = new MySQLDao(); // 直接依赖具体实现 } // IOC方式(松耦合) class UserService { @Autowired // 容器注入 private UserDao dao; // 依赖接口 } ``` --- ### **2. 实现原理** #### **(1) 核心组件** | 组件 | 作用 | 数学符号表示 | |---------------------|-----------------------------|------------------| | Bean定义 | 描述类如何实例化(XML/注解/Java配置) | $BeanDef = \{class, scope, init...\}$ | | Bean工厂 | 负责创建和管理Bean实例 | $Factory: BeanDef \rightarrow Object$ | | 依赖解析器 | 处理@Autowired等注解的依赖关系 | $Resolver: Object \times Field \rightarrow Bean$ | #### **(2) 生命周期流程** $$ \text{初始化流程} = \begin{cases} \text{加载配置} \rightarrow \text{实例化Bean} \rightarrow \text{属性注入} \rightarrow \text{初始化方法} \\ \text{运行时} \rightarrow \text{从容器获取Bean} \rightarrow \text{使用} \\ \text{销毁} \rightarrow \text{调用销毁方法} \end{cases} $$ --- ### **3. 关键设计模式** #### **(1) 工厂模式** ```java // Bean工厂抽象实现 public interface BeanFactory { Object getBean(String name); <T> T getBean(Class<T> requiredType); } ``` #### **(2) 反射机制** - **类实例化**:`Class.forName().newInstance()` - **依赖注入**:通过Field.set(obj, value)实现属性赋值 - **数学表达**: $$ \text{反射操作} = \mathcal{R}(ClassName) \rightarrow \text{Method/Field} $$ --- ### **4. Spring IOC容器实现** #### **(1) 容器层级** $$ \begin{align*} \text{BeanFactory} & \leftarrow \text{基础容器} \\ \text{ApplicationContext} & \leftarrow \text{扩展容器(支持AOP、事件等)} \end{align*} $$ #### **(2) 典型注解** | 注解 | 作用 | 数学表达 | |---------------|-----------------------------|------------------------| | @Component | 标记类为Bean | $Class \xrightarrow{@Component} BeanDef$ | | @Autowired | 自动注入依赖 | $Field \xrightarrow{@Autowired} Bean_{target}$ | | @Scope | 控制Bean作用域(单例/原型) | $BeanDef \times Scope \rightarrow Instance$ | --- ### **5. 实际案例** #### **(1) XML配置方式** ```xml <!-- 定义Bean --> <bean id="userDao" class="com.example.JdbcUserDao"/> <bean id="userService" class="com.example.UserService"> <property name="dao" ref="userDao"/> </bean> ``` #### **(2) Java注解方式** ```java @Configuration public class AppConfig { @Bean public UserDao userDao() { return new JdbcUserDao(); } } @Service public class UserService { @Autowired private UserDao dao; // 自动注入 } ``` --- ### **6. 数学验证解耦效果** 设系统有$n$个组件,传统硬编码方式需要维护: $$ C_{\text{传统}} = O(n^2) \text{个依赖关系} $$ 采用IOC容器后: $$ C_{\text{IOC}} = O(n) \text{个Bean定义} $$ --- ### **7. 优势分析** 1. **降低耦合度**:$\text{类间依赖} \downarrow$ 2. **提升可测试性**:通过Mock注入实现单元测试 3. **统一配置管理**:$BeanDef \rightarrow \text{集中式配置}$ 4. **便于扩展**:新增实现类只需修改配置,无需改动业务代码 --- ### **总结** IOC通过将对象控制权转移给容器,实现了: 1. **依赖反转**:由容器管理对象依赖($A \nrightarrow B \rightarrow A \leftarrow Container \rightarrow B$) 2. **生命周期管理**:统一控制创建、初始化、销毁过程 3. **配置与代码分离**:通过元数据(XML/注解)描述组件关系 在Spring等现代框架中,IOC容器配合DI机制,已成为构建松耦合、可维护系统的基石。其数学本质是通过容器函数$f(config)$将离散的对象关系转化为可管理的拓扑结构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值