深入探究控制反转(IOC)与依赖注入(DI)间的关系


思考,输出,沉淀。用通俗的语言陈述技术,让自己和他人都有所收获。

作者:毅航😜


谈及IOC我想大多数后端开发者一定会想到Spring,这主要是因为Spring 框架将IOC设计原则贯穿于整个框架中,并通过依赖注入(DI)和面向切面编程(AOP)等特性,实现了一种轻量级、灵活的IOC容器,进而将所有的Bean信息都交由容器管理,进一步避免了开发人员繁琐的使用new关键字来构建对象,进一步实现解耦的目的。

IOC的本质

IOC全称为Inversion of Control译为中文即控制反转 。有了反转必然便会有正转,这一点就像有反向代理的出现必然会有正向代理一样。那什么又是正转呢?通俗来看,如果我们通过手动方式去创建对象维护对象间的依赖关系的话,那便是正转。 这样说可能比较晦涩,我们举一个简单的例子来看,例如:

java 复制代码
@RestController
@RequestMapping("/users")
public class UserController {


    private UserService userService = new UserServices()
  
  
    @PostMapping("/add-user")
    public ResponseEntity getBookAndUserInfo(@RequestBody UserInfo userInfo ) {

    return userService.addUser(userInfo);
}

在上述例子中,UserController需要依赖于userService来完成的对象的操作逻辑,为了实现这一目的,我们通过使用new关键字的方式在UserController构建一个名为userService的对象来满足这一依赖关系。这便是所谓的正转,即应用程序需要人为主动的去维护对象间的依赖关系,并且自己创建对象。

知晓了正转后,我们再来看反转。其实,反转的核心在于将程序中对象的创建、依赖注入和生命周期管理等控制权转移给外部容器或框架,而不是由程序自身来负责。换言之,IOC的本质是反转了传统的控制流程,使得程序不再控制对象的创建和管理,而是由外部容器来控制。

通过我们之前对于正转的介绍,不难发现,在传统的程序设计中,对象之间的依赖关系通常是硬编码在代码中的,即一个对象直接依赖于另一个对象的具体实现。 这进而便导致了对象间高耦合的发生。而IOC的出现恰恰有效的降低了对象间的耦合关系。

具体到Spring来看,其通过将对象的创建和管理交给容器来处理,从而降低了对象之间的直接依赖关系,实现了解耦的目的。而在IOC的设计中,对象之间的依赖关系通常是通过接口或抽象类来定义的,具体的实现则由容器在运行时动态地注入到对象中。

事实上,IOC容器负责管理应用程序中的各个组件(对象)的生命周期,包括创建、配置、组装、初始化和销毁等过程。开发者只需要在配置文件或注解中声明对象之间的依赖关系,而不需要直接在代码中硬编码依赖关系。

DI:依赖注入

在开始分析两者关系之前,希望你能明白:所谓的依赖注入(Dependency Injection,DI)是控制反转(Inversion of Control,IoC)的一种具体实现方式罢了。 我们知道,在传统的程序设计中,对象通常会在自己的内部负责创建和管理依赖对象,导致了高耦合度和低灵活性。而使用依赖注入的机制引入后,对象不再负责创建和管理依赖对象,而是通过外部容器来将依赖对象注入到目标对象中,从而实现了对象之间的解耦。

事实上,依赖注入的原理很简单,即目标对象不再直接依赖于具体的实现,而是依赖于接口或抽象类。外部容器负责创建依赖对象的实例,并将其注入到目标对象中 。这样一来目标对象只需要声明依赖关系,而不需要关心依赖对象的创建和管理,从而降低了对象之间的耦合度。

总之,DIIOC密切相关,可以说DIIOC的一种具体实现方式。其中IOC描述了程序中对象控制权的反转,即将对象的创建和管理交给外部容器来处理。而DI则是实现IOC的手段之一,它通过依赖注入的方式来实现对象之间的解耦。DI将对象的依赖关系从对象内部移动到了外部容器中,使得系统更加灵活、可维护和可扩展。

换言之,依赖注入是一种实现IOC的具体方式,通过将对象之间的依赖关系从对象内部移动到外部容器中,实现了对象之间的解耦,提高了系统的灵活性和可维护性。

IOC思想的应用

正如前文所说,控制反转(IOC,Inversion of Control)是一种设计思想,因此无论在前端还是后端主流框架都能看到IOC思想的应用。

在前端主流框架中(如Vue.js、React.js、Angular等),IOC思想主要通过依赖注入(DI,Dependency Injection)来实现。这些框架提供了便捷的方式来管理组件之间的依赖关系,使得开发者可以更轻松地组织和管理代码。通过依赖注入,可以实现组件之间的解耦,提高了代码的灵活性和可维护性。

例如,Vue.js 提倡将应用程序拆分成组件,每个组件负责自己的状态和行为,通过 props events 来实现组件之间的通信,这可以看作是一种轻量级的 IOC思想,即组件之间的依赖关系由父组件动态地注入给子组件,而子组件则通过事件向上传递状态。这种组件化的设计理念使得Vue.js 应用程序更加灵活、可维护和可扩展。

在后端主流框架中(如Spring、Django、Express等),IOC思想主要通过依赖注入容器(DI Container)来实现。这些框架提供了容器来管理应用程序中的组件,负责对象的创建、配置和生命周期管理等任务。开发者只需要声明组件之间的依赖关系,而不需要直接在代码中进行对象的创建和管理,从而降低了系统的耦合度,提高了代码的可维护性和可测试性。

例如,在Spring框架中,可以通过注解或者XML配置文件来声明Bean和它们之间的依赖关系,而Spring容器则负责实例化和管理这些Bean

总结

至此,文章主要介绍了控制反转(IOC)和依赖注入(DI)的概念、本质以及它们在现代软件开发中的应用。具体来看,IOC将对象的创建和管理权交给外部容器,从而降低了对象之间的耦合度,实现了解耦的目的。DI作为IOC的具体实现方式,通过依赖注入的方式实现了对象之间的解耦,提高了系统的灵活性和可维护性。

最后,希望文章对你理解控制反转(IOC)和依赖注入(DI)有所帮助~~~

相关推荐
金池尽干31 分钟前
设计模式之——观察者模式
观察者模式·设计模式
也无晴也无风雨1 小时前
代码中的设计模式-策略模式
设计模式·bash·策略模式
monkey_meng1 小时前
【Rust中的迭代器】
开发语言·后端·rust
余衫马1 小时前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng1 小时前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
阑梦清川1 小时前
在鱼皮的模拟面试里面学习有感
学习·面试·职场和发展
paopaokaka_luck5 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
码农小旋风7 小时前
详解K8S--声明式API
后端
Peter_chq7 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml47 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍