【Spring】Spring依赖注入与控制反转理解

Spring是一个庞大的框架,封装了很多成熟的功能,能够让我们无需重复造轮子;其次,它使用IOC进行依赖管理,利用JAVA的反射机制,将实例的初始化交给Spring,Spring可以通过配置文件管理实例,我们就不用自己初始化实例啦。

有人会问 “那我们可以直接使用工厂模式呀。工厂模式也可以管理实例的初始化呀,为什么一定要使用Spring呢?” 这是因为IOC是通过反射机制来实现的。当我们的需求出现变动时,工厂模式会需要进行相应的变化。但是IOC的反射机制允许我们不重新编译代码,因为它的对象都是动态生成的。

一.什么是依赖注入和控制反转?

控制反转:即IOC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。

依赖注入:基本原则是:应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IoC容器负责。

依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。
具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。

二. 实例解释

不管是依赖注入,还是控制反转,都说明Spring采用动态、灵活的方式来管理各种对象。对象与对象之间的具体实现互相透明。在理解依赖注入之前,看如下这个问题在各种社会形态里如何解决:一个人(Java实例,调用者)需要一把斧子(Java实例,被调用者)。

(1) 原始社会里,几乎没有社会分工。需要斧子的人(调用者)只能自己去磨一把斧子(被调用者)。对应的情形为:Java程序里的调用者自己创建被调用者。
这种情况下,Java实例的调用者创建被调用的Java实例,必然要求被调用的Java类出现在调用者的代码里。无法实现二者之间的松耦合。

(2) 进入工业社会,工厂出现。斧子不再由普通人完成,而在工厂里被生产出来,此时需要斧子的人(调用者)找到工厂,购买斧子,无须关心斧子的制造过程。对应Java程序的简单工厂的设计模式。
这种情况下,调用者无须关心被调用者具体实现过程,只需要找到符合某种标准(接口)的实例,即可使用。此时调用的代码面向接口编程,可以让调用者和被调用者解耦,这也是工厂模式大量使用的原因。但调用者需要自己定位工厂,调用者与特定工厂耦合在一起。

(3) 进入“按需分配”社会,需要斧子的人不需要找到工厂,坐在家里发出一个简单指令:需要斧子。斧子就自然出现在他面前。对应Spring的依赖注入。
这种情况下,调用者无须自己定位工厂,程序运行到需要被调用者时,系统自动提供被调用者实例。事实上,调用者和被调用者都处于Spring的管理下,二者之间的依赖关系由Spring提供。

三.总结:

所谓依赖注入,是指程序运行过程中,如果需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部的注入。Spring的依赖注入对调用者和被调用者几乎没有任何要求,完全支持对POJO之间依赖关系的管理。

### 依赖注入控制反转的概念 依赖注入(Dependency Injection, DI)是一种设计模式,用于实现控制反转(Inversion of Control, IoC)。IoC 是一种设计理念,在这种理念下,对象不再自己创建所依赖的对象,而是由外部提供这些依赖。这种方式使得组件之间更加松散耦合,提高了代码的可测试性灵活性[^1]。 DI 主要通过三种方式实现:构造函数注入、属性注入以及方法注入。其中最常见的是构造函数注入方法注入。在 Laravel 这样的框架中,可以通过类的构造函数声明依赖关系,并将所需的服务作为参数传入;也可以通过特定的方法接收依赖服务[^2]。 当应用了 DI IoC 后,开发者不需要手动管理各个模块间的实例化过程及其相互间的关系,因为这一切都交给了容器去处理。这样不仅简化了开发流程,还增强了系统的扩展能力[^3]。 ### 使用方法及示例 #### 构造函数注入 这是推荐的方式之一,它确保了一个对象在其生命周期内始终拥有其所需的全部协作对象: ```php class EmailService { protected $mailer; public function __construct(MailerInterface $mailer) { // 注入 Mailer 接口的具体实现 $this->mailer = $mailer; } public function sendEmail($to, $subject, $body){ return $this->mailer->send($to,$subject,$body); } } ``` #### 方法注入 对于某些情况下只需要临时使用的依赖项,则可以采用此形式来进行传递: ```php class ReportGenerator { private $dataStore; public function generateReport(DataStoreInterface $store){ // 在调用时才决定具体的数据存储接口实现 $this->dataStore = $store; // ... 报告生成功能逻辑 ... } } ``` 以上两种方式均体现了如何利用 DI 来构建更灵活的应用程序结构,同时也展示了 IoC 的核心思想——即把原本属于内部的责任转移到外界环境中解决。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值