控制反转(IoC)与依赖注入(DI)

本文深入探讨了控制反转(IoC)与依赖注入(DI)的概念及其在软件开发中的应用。详细介绍了IoC如何通过将对象的控制权转移给容器来简化组件间的依赖管理,并对比了依赖查找与依赖注入的不同实现方式。

Quotes: http://zhangjunhd.blog.51cto.com/113473/126530

 

1.控制反转(Inversion of Control)与依赖注入(Dependency Injection)

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

   IoC是一个很大的概念,可以用不同的方式来实现。其主要实现方式有两种:<1>依赖查找(Dependency Lookup):容器提供回调接口和上下文环境给组件。EJB和Apache Avalon都使用这种方式。<2>依赖注入(Dependency Injection):组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。后者是时下最流行的IoC类型,其又有接口注入 (Interface Injection),设值注入(Setter Injection)和构造子注入(Constructor Injection)三种方式。

控制反转(IoC)与依赖注入(DI)

  图1 控制反转概念结构

   依赖注入之所以更流行是因为它是一种更可取的方式:让容器全权负责依赖查询,受管组件只需要暴露JavaBean的setter方法或者带参数的构造子 或者接口,使容器可以在初始化时组装对象的依赖关系。其与依赖查找方式相比,主要优势为:<1>查找定位操作与应用代码完全无 关。<2>不依赖于容器的API,可以很容易地在任何容器以外使用应用对象。<3>不需要特殊的接口,绝大多数对象可以做到完全 不必依赖容器。

  2.好莱坞原则

  IoC体现了好莱坞原则,即“不要打电话过来,我们会打给你”。第一次遇到好莱坞原则是在了解模板方法(Template Mathod)模式的时候,模板方法模式的核心是,基类(抽象类)定义了算法的骨架,而将一些步骤延迟到子类中。

控制反转(IoC)与依赖注入(DI)

  图2 模板方法模式类图

   现在来考虑IoC的实现机制,组件定义了整个流程框架,而其中的一些业务逻辑的实现要借助于其他业务对象的加入,它们可以通过两种方式参与到业务流程 中,一种是依赖查找(Dependency Lookup),类似与JDNI的实现,通过JNDI来找到相应的业务对象(代码1),另一种是依赖注入,通过IoC容器将业务对象注入到组件中。

  3. 依赖查找(Dependency Lookup)

  下面代码展示了基于JNDI实现的依赖查找机制。

public class MyBusniessObject{
 private DataSource ds;
 private MyCollaborator myCollaborator;
 public MyBusnissObject(){
Context ctx = null;
try{
  ctx = new InitialContext();
  ds = (DataSource) ctx.lookup(“java:comp/env/dataSourceName”);
  myCollaborator =
(MyCollaborator) ctx.lookup(“java:comp/env/myCollaboratorName”);
  }……

  代码1依赖查找(Dependency Lookup)代码实现

  依赖查找的主要问题是,这段代码必须依赖于JNDI环境,所以它不能在应用服务器之外运行,并且如果要用别的方式取代JNDI来查找资源和协作对象,就必须把JNDI代码抽出来重构到一个策略方法中去。

  4. 依赖注入(Dependency Injection)

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

下面分别演示3中注入机制。

  代码2 待注入的业务对象Content.java

package com.zj.ioc.di;
public class Content {
  public void BusniessContent(){
    System.out.println("do business");
  }
  
  public void AnotherBusniessContent(){
    System.out.println("do another business");
  }
}

   MyBusniess类展示了一个业务组件,它的实现需要对象Content的注入。代码3,代码4,代码5,6分别演示构造子注入 (Constructor Injection),设值注入(Setter Injection)和接口注入(Interface Injection)三种方式。

  代码3构造子注入(Constructor Injection)MyBusiness.java

package com.zj.ioc.di.ctor;
import com.zj.ioc.di.Content;
public class MyBusiness {
  private Content myContent;
  public MyBusiness(Content content) {
    myContent = content;
  }
  
  public void doBusiness(){
    myContent.BusniessContent();
  }
  
  public void doAnotherBusiness(){
    myContent.AnotherBusniessContent();
  }
}

  代码4设值注入(Setter Injection) MyBusiness.java

package com.zj.ioc.di.set;
import com.zj.ioc.di.Content;
public class MyBusiness {
  private Content myContent;
  public void setContent(Content content) {
    myContent = content;
  }
  
  public void doBusiness(){
    myContent.BusniessContent();
  }
  
  public void doAnotherBusiness(){
    myContent.AnotherBusniessContent();
  }
}

代码5 设置注入接口InContent.java

package com.zj.ioc.di.iface;
import com.zj.ioc.di.Content;
public interface InContent {
  void createContent(Content content);
}

  代码6接口注入(Interface Injection)MyBusiness.java

package com.zj.ioc.di.iface;
import com.zj.ioc.di.Content;
public class MyBusiness implements InContent{
  private Content myContent;
  public void createContent(Content content) {
    myContent = content;
  }
  
  public void doBusniess(){
    myContent.BusniessContent();
  }
  
  public void doAnotherBusniess(){
    myContent.AnotherBusniessContent();
  }
}

  5.依赖拖拽(Dependency Pull)

  最后需要介绍的是依赖拖拽,它在Spring中得到广泛应用。

  代码7 依赖拖拽示例

public static void main(String[] args) throws Exception{
//get the bean factory
BeanFactory factory = getBeanFactory();
MessageRender mr = (MessageRender) factory.getBean(“renderer”);
mr.render();
}

  而通常IoC容器的配置可以通过一个xml文件完成。

  使用这种方式对对象进行集中管理,使用依赖拖拽与依赖查找本质的区别是,依赖查找是在业务组件代码中进行的,而不是从一个集中的注册处,特定的地点执行。

  本文出自 “子 孑” 博客,请务必保留此出处http://zhangjunhd.blog.51cto.com/113473/126530

基于数据驱动的 Koopman 算子的递归神经网络模型线性化,用于纳米定位系统的预测控制研究(Matlab代码实现)内容概要:本文围绕“基于数据驱动的 Koopman 算子的递归神经网络模型线性化,用于纳米定位系统的预测控制研究”展开,提出了一种结合数据驱动方法Koopman算子理论的递归神经网络(RNN)模型线性化方法,旨在提升纳米定位系统的预测控制精度动态响应能力。研究通过构建数据驱动的线性化模型,克服了传统非线性系统建模复杂、计算开销大的问题,并在Matlab平台上实现了完整的算法仿真验证,展示了该方法在高精度定位控制中的有效性实用性。; 适合人群:具备一定自动化、控制理论或机器学习背景的科研人员工程技术人员,尤其是从事精密定位、智能控制、非线性系统建模预测控制相关领域的研究生研究人员。; 使用场景及目标:①应用于纳米级精密定位系统(如原子力显微镜、半导体制造设备)中的高性能预测控制;②为复杂非线性系统的数据驱动建模线性化提供新思路;③结合深度学习经典控制理论,推动智能控制算法的实际落地。; 阅读建议:建议读者结合Matlab代码实现部分,深入理解Koopman算子RNN结合的建模范式,重点关注数据预处理、模型训练控制系统集成等关键环节,并可通过替换实际系统数据进行迁移验证,以掌握该方法的核心思想工程应用技巧。
### 控制反转IoC依赖注入DI)的联系相互关系 #### 1. **控制反转IoC)的本质** 控制反转是一种软件设计原则,核心在于将对象的创建和管理权从应用程序内部转移到外部容器中。这种转变使得开发人员无需再手动编写复杂的对象初始化逻辑,从而降低了模块间的耦合度[^1]。具体而言,IoC改变了传统程序中对象创建的方式——原本是由程序员通过`new`关键字显式创建对象,而现在这一职责被委托给了像Spring这样的外部容器。 例如,在没有采用IoC的情况下,一个类可能如下所示: ```java public class UserService { private UserRepository userRepository; public UserService() { this.userRepository = new UserRepository(); // 手动创建依赖 } } ``` 而使用IoC后,则变为由容器负责实例化和组装依赖关系。 --- #### 2. **依赖注入DI)的作用** 依赖注入是实现控制反转的具体技术手段之一。它通过某种机制(如构造器注入、Setter方法注入或字段注入),将依赖项传递给目标对象,从而使目标对象能够专注于自身的业务逻辑而不必关心依赖项的来源[^3]。换句话说,DI定义了如何在运行时动态地为对象提供其所需要的服务或其他组件。 以下是一个基于构造器注入的例子: ```java @Component public class UserService { private final UserRepository userRepository; @Autowired public UserService(UserRepository userRepository) { // 构造器注入 this.userRepository = userRepository; } public void performAction() { userRepository.save(); } } ``` 在这里,`UserService` 不再自己创建 `UserRepository` 实例,而是等待Spring容器将其注入进来。 --- #### 3. **两者的内在联系** 尽管IoCDI看似独立的概念,实际上它们密不可分: - **IoC 是一种高层次的设计理念**,旨在解决整体架构中的对象管理和依赖问题。 - **DI 则是 IoC 的主要实现方式**,提供了具体的解决方案来满足IoC的目标。 更进一步地说,IoC描述了一个宏观的方向:即“谁应该负责对象及其依赖的管理”。而DI则细化到了微观层面,说明了“怎样才能有效地完成这项工作”[^4]。因此,可以认为DIIoC的一部分或者说是其实现途径之一。 为了更好地理解这一点,我们可以回顾一下经典的比喻:“IoC就像一座房子的整体结构规划图,告诉你哪些房间该放什么家具;而DI则是施工队按照图纸一步步把每件家具摆放到指定位置的过程。” --- #### 4. **总结对比** | 特性 | 控制反转IoC) | 依赖注入DI) | |------------------|------------------------------------------------|-------------------------------------------| | 定义域 | 提供了一种新的控制流方向 | 明确指出了如何装配依赖 | | 关注点 | 整体架构层面上的对象管理及依赖关系 | 单个对象级别的依赖传递 | | 是否可替代 | 可以通过多种方式实现 | 基本上局限于几种固定的注入形式 | 综上所述,IoC代表了一种广义的思想指导方针,而DI充当着落实这些思想的关键工具角色。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值