首页 > 其他分享 >IOC与DI

IOC与DI

时间:2024-04-01 20:34:07浏览次数:23  
标签:依赖 name DI 对象 nest IOC class 注入

1. 概念

IoC(Inversion of Control)和 DI(Dependency Injection)是面向对象编程中的两个相关概念,它们主要用于解决程序中的依赖管理和解耦问题。

2. IOC(控制反转)

  • 控制反转是一种设计原则,它涉及到对象创建和依赖管理的方式。在传统的编程方式中,对象通常自行创建或查找它们依赖的对象。而在IoC模式下,这种创建和查找依赖对象的责任从应用程序代码中转移到了外部的第三方(通常是框架或容器),即所谓的“控制权反转”给了容器。
  • 核心思想:对象不再直接控制其依赖对象的创建和生命周期管理,而是由外部容器负责这些工作。容器知道哪些对象需要哪些依赖,并负责在适当的时候将依赖注入到需要它们的对象中。通过这种方式,对象之间的依赖关系变得更加透明,降低了耦合度,提高了代码的可重用性和可测试性。

3. DI

  • 依赖注入是实现IoC的一种具体设计模式或技术手段,是IoC原则的常见实现方式之一。
  • 概念:依赖注入是指在对象实例化或运行时,由外部容器或框架负责将依赖对象(服务、组件、模块等)注入到需要它们的对象(客户端、消费者)中。注入可以是通过构造函数、属性(setter方法)或接口方法等方式进行。
  • 目的:通过依赖注入,对象不再关心依赖对象的具体实现细节和生命周期管理,只需声明它需要哪些依赖(接口或抽象类型),由外部容器负责提供正确的依赖实例。这样,对象间的依赖关系变得松散,容易更改,有利于代码的解耦和测试。

4. 案列

class A {
    name: string
    constructor(name: string) {
        this.name = name
    }
}
 
 
class B {
    age:number
    entity:A
    constructor (age:number) {
        this.age = age;
        this.entity = new A('xt')
    }
}
 
const c = new B(18)
 
c.entity.name

我们可以看到,B 中代码的实现是需要依赖 A 的,两者的代码耦合度非常高。当两者之间的业务逻辑复杂程度增加的情况下,维护成本与代码可读性都会随着增加,并且很难再多引入额外的模块进行功能拓展


class A {
    name: string
    constructor(name: string) {
        this.name = name
    }
}
 
 
class C {
    name: string
    constructor(name: string) {
        this.name = name
    }
}
//中间件用于解耦
class Container {
    modeuls: any
    constructor() {
        this.modeuls = {}
    }
    provide(key: string, modeuls: any) {
        this.modeuls[key] = modeuls
    }
    get(key) {
        return this.modeuls[key]
    }
}
 
const mo = new Container()
mo.provide('a', new A('xt1'))
mo.provide('c', new C('xt2'))
 
class B {
    a: any
    c: any
    constructor(container: Container) {
        this.a = container.get('a')
        this.c = container.get('c')
    }
}
 
new B(mo)

其实就是写了一个中间件,来收集依赖,主要是为了解耦,减少维护成本

5. nest中如何使用的IoC

5.1. 创建项目
nest new nest-ioc

pnpm start

浏览器访问 http://localhost:3000 就可以看到 nest 服务返回的 hello world

5.2. 它是怎么创建对象的

(红色报错的地方是eslint代码检测问题,我后面再教大家如何配置,现在先忽略)

我们可以看到在app.service,他声明了 @Injectable,代表这个 class 可注入,那么 nest 就会把它的对象放到 IOC 容器里

当然你还可以写成这样

(前者是构造器注入,后者是属性注入)

app.controller声明了 @Controller,代表这个 class 可以被注入,nest 也会把它放到 IoC 容器里。

app.controller 的构造器参数依赖了 app.service。

为什么 Controller 是单独的装饰器?

因为 Service 是可以被注入也是可以注入到别的对象的,所以用 @Injectable 声明。而 Controller 只需要被注入,所以 nest 单独给它加了 @Controller 的装饰器。

通过 @Module 声明模块,其中 controllers 是控制器,只能被注入

providers 里可以被注入,也可以注入别的对象,比如这里的 AppService。

当执行start的时候 main.ts的内容就会被执行,那么 nest 就会从 AppModule 开始解析 class 上通过装饰器声明的依赖信息,自动创建和组装对象

5.3. 模块机制
nest g module user

可以看到 他帮我们生成了代码,并自动的往app.module 里自动 imports 了这个模块

我们在来生成一个service

nest g service user

可以看到 他帮我们生成了代码,并自动添加到 user.module 的 providers 中

我们修改一下user.service的代码并在user.module中exports

在之前我们说到过,app.module中是不是已经引用了user.module了,那么他现在他就可以注入exports 的 UserService 了

标签:依赖,name,DI,对象,nest,IOC,class,注入
From: https://blog.csdn.net/wangyuiba1314/article/details/137224313

相关文章

  • vue3 设置el-dialog height超过滚动条
     方法一:<stylescoped>::v-deep.el-dialog.el-dialog-body{height:500px;overflow-y:auto;}</style> 如果要设置动态的高度话,则要在setup里面设置 <script>exportdefaultdefineComponent({setup:{constcssContent=ref({heigh......
  • Linux 安装 Redis (Docker)
    Linux安装Redisdockerpullredis由于容器内目录下没有redis.conf,导致/mydata/redis/conf/redis.conf认为是目录所以先创建配置文件mkdir-p/mydata/redis/conftouch/mydata/redis/conf/redis.confmkdir-p/mydata/redis/conf:创建一个目录/mydata/redis/conf,-p如......
  • 菜鸟记录:c语言实现PAT甲级1010--Radix
    很长时间没做,忙于考研和实习,久违的的拾起了算法。做了很长时间,其实总体思路还是很简单的,但满分不知道为什么就是到不了,又因为网上很多答案包括柳神的都是c++,无法参透,姑且只能这样了。Givenapairofpositiveintegers,forexample,6and110,canthisequation6=110bet......
  • 【NoSQL】SpringBoot+Redis简单使用
    【NoSQL】SpringBoot+Redis简单使用Redis是一款key-value存储结构的内存级NoSQL数据库;支持多种数据存储格式、支持持久化、支持集群windows下载:https://github.com/tporadowski/redis/releases<dependency><groupId>org.springframework.boot</groupId><artifactId......
  • Android Studio安装超详细步骤
    前言在移动互联网时代,作为一个测试工程师,更多的工作也是测试App,在学习了App自动化测试之后,想要实践,就要先安装好一套App自动化测试的环境,第一步就是要安装好AndroidStudio环境,这样就可以使用adb工具,并且使用appium来运行我们的测试脚本。本文就来给大家介绍一下安装androidstud......
  • POI2005 KOS-Dicing
    网络流#二分考虑二分答案,用\(Dinic\)来\(check\)具体来说,就是对每一个人限制流量,然后检查能不能把所有场全部流满#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#defineullunsignedlonglong#defineALL(a)(a).begin(),(a).end()#definepb......
  • WPF如何使用 System.Windows.Forms.FolderBrowserDialog
    WPF如何使用System.Windows.Forms.FolderBrowserDialog在WPF中,如果你想使用System.Windows.Forms.FolderBrowserDialog来选择文件夹,你需要添加对WinForms的引用,因为FolderBrowserDialog是WindowsForms的一部分,不是WPF的一部分。下面是如何在WPF应用程序中使用FolderBro......
  • 在.Net中操作redis
    在.Net中操作redis一、环境.Net7redis7.2.4二、所需类包StackExchange.Redis三、连接redis信息appsettings.json配置redis连接信息//Redis配置//"Redis":{//"Default":{//"Connection":"",//连接地址,端口号,密码//"Instance......
  • Django 中集成 CKEditor 富文本编辑器详解
    Django中集成CKEditor富文本编辑器详解原文链接:https://blog.csdn.net/Rocky006/article/details/135130010概要在Web应用中,富文本编辑器是提高用户体验的重要组件之一。CKEditor是一款流行的、功能丰富的富文本编辑器。在Django项目中集成CKEditor不仅可以提升内容......
  • Higress 基于自定义插件访问 Redis
    作者:钰诚简介基于wasm机制,Higress提供了优秀的可扩展性,用户可以基于Go/C++/Rust编写wasm插件,自定义请求处理逻辑,满足用户的个性化需求,目前插件已经支持redis调用,使得用户能够编写有状态的插件,进一步提高了Higress的扩展能力。文档在插件中调用Redis[1]中提供了......