3. IoC 与DI

server/2024/10/22 7:53:31/

一、 定义

  • IoC,即控制反转,把对象的调用权交给容器,通过容器来实现对象的装配和管理。
  • DI,即依赖注入,对象之间依赖关系由容器在运行期决定,由容器动态的将依赖关系注入到对象之中。
  • DI,是对IoC更完善的描述。

二、 疑问

  • 谁依赖谁?【对象实例化依赖容器】
  • 为什么要依赖?【对象实例化通过容器自动得到外部依赖】
  • 谁注入谁?【容器注入对象的依赖到对象中】
  • 注入了什么?【注入了对象的外部依赖】

三、 Hyperf的依赖注入的实现

  • hyperf/di 组件提供功能支持
  • 更符合长生命周期的应用使用
  • 提供了 注解、注解注入、AOP
  • 基于 PSR-11 实现,可独立应用于其它框架

四、注入方式

  • 通过构造方法注入
  • 通过#[Inject]注解注入

五、 注入类型

  • 简单对象注入
  • 抽象对象注入
  • 工厂对象注入

六、 实例

① 【简单对象注入】

  • 假设存在一个UserService类,在IndexController类中引用它
php"><?php
// UserService类
namespace App\Service;
class UserService {public fucntion getInfoById(int $id) {// 假设存在一个 Info  实体return (new Info())-> fill($id);} 
}

1. 构造函数的形式

构造函数定义依赖类的 Typehint
IndexController 在被DI容器创建时,会自动注入相关依赖

php"><?php
// IndexController
namespace App\Controller;
class IndexController {private $userService;public function __construct(UserService $userService) {$this->userService = $userService;}public function index() {return $this->userService->getInfoById(1);}
}

2. Inject注解的形式

在类成员属性上定义 #[Inject] 注解 和 @var,完成依赖注入

php"><?php
namespace App\Controller;
use App\Service\UserSerice;
use Hyperf\Di\Annotation\Inject;
class IndexController {#[Inject]private UserService $userService;public function index() {return $this->userService->getInfoById(1);}
}

②【抽象对象注入】

1. 定义一个接口类 UserServiceInterface

UserService 实现接口类

php"><?php
namespace App\Service;// UserServiceInterface 接口类
interface UserServiceInterface {public function getInfoById(int $id);
}// UserService 实现类
class UserService implements UserServiceInterface {public function getInfoById(int $id) {return (new Info())->fill($id);}
}

2. 在对应的位置,进行 接口类 与 实现类 的关系绑定

php"><?php
// 在 config/dependencies.php
use App\Service\UserServiceInterface;
use App\Service\UserService;
return ['dependencies' => [UserServiceInterface::class =>UserService::class,],
];

3. 通过以接口类作为 Typehint 注入对应的实现类

php"><?php
namespace App\Controller;use App\Service\UserServiceInterface;
use Hyperf\Di\Annotation\Inject;class IndexController {/*** @var UserServiceInterface*/#[Inject]private $userService;public function index() {return $this-<userService->getInfoById(1);}
}

③【工厂对象注入】

  • 通过容器来创建一个复杂类,如构造函数需要接收参数的,参数应是应用参数,而不是动态的请求参数。

  • DI管理的对象是单例

    php"><?php
    namespace App\Service;class UserService inplements userServiceInterface {private $enableCache;public function __construct(bool $enableCache) {$this->enableCache = $enableCache;}public function getInfoById(int $id) {return (new Info())->fill($id);}
    }
    
  • 通过工厂类创建复杂的对象

    • 定义一个工厂类,在__invoke()方法内实现对象的创建并返回
    • make() 函数创建短声明周期对象
    php"><?php
    namespace App\Service;
    use Hyperf\Contract\ConfigInterface;
    use Psr\Container\ContainerInterface;class UserServiceFactory {// __invoke() 方法写成对象的生产// 方法参数会自动注入一个当前的容器实例// 通过$container对象可以取出hyperf\Di容器中的任意对象public function __invoke(ContainerInterface $container) {$config = $container->get(ConfigInterface::class);// 假设对应的配置的 key 为 cache.enable$enableCache = $config->get('cache.enable', false);// make(string $name, array $parameters=[]) 方法 等同于 new,使用 make() 方法是为了允许 AOP 的介入,而直接 new 会导致 AOP 无法正常介入流程return make(UserService::class, compact('enableCache'));}
    }
    
  • 调整接口类与工厂类的关系,注入的即为 由工厂类创建的对象

    php"><?php
    // 在 config/dependencies.php
    use App\Service\UserServiceInterface;
    use App\Service\UserServiceFactory;
    return ['dependencies' => [UserServiceInterface::class =>UserServiceFactory::class,],
    ];
    

④ 注入容器自身

  • 直接注入 Psr\Container\ContainerInterface
  • 通过 Hyperf\Utils\ApplicationContext::getContainer() 获得

七、 注解 和 DI 的总结

  1. 注解只是元数据定义,实现功能时不利用这些数据的话,没有任何作用。
  2. 使用了注解的对象,必须基于 Hyperf 和 DI容器来创建对象才能生效。
  3. 注解可以用在类、类方法、类成员属性上。
  4. DI容器是负责管理 对象的创建对象的依赖管理 的。
  5. DI容器创建出来的对象是个单例,是长生命周期对象。
  6. 通过 $container->make() 方法 或 make() 函数创建短生命周期对象。
  7. 通过 new 来实例化的对象注解 不会生效,依赖需自行管理。

http://www.ppmy.cn/server/133839.html

相关文章

鸿蒙开发超好用的 UI 组件和工具类库 BasicLibrary

大家好&#xff0c;我是 V 哥。你在学习HarmonyOS NEXT 开发吗&#xff0c;今天 V 哥给你推荐一款超好用的三方库BasicLibrary&#xff0c;BasicLibrary 是一个基于 API 11 封装的基本库&#xff0c;旨在提升鸿蒙开发效率。它包含了一些常用的 UI 组件和实用工具类&#xff0c;…

Qt 实战(11)样式表 | 11.1、样式表简介

文章目录 一、样式表简介1、简介2、样式表语法2.1、样式规则2.2、选择器类型2.3、伪状态2.4、设置子控件状态 3、样式表继承与优先级3.1、样式表继承3.2、样式表优先级3.3、解决冲突3.4、样式表层叠 4、总结 前言&#xff1a; 在开发图形用户界面&#xff08;GUI&#xff09;应…

React 中级阶段学习计划

React 中级阶段学习计划 目标 掌握状态管理和路由。能够调用API并处理异步数据。学会使用CSS-in-JS和CSS Modules进行样式处理。 学习内容 状态管理 React Context API Context API&#xff1a;用于在组件树中传递数据&#xff0c;避免多层props传递。示例&#xff1a;im…

C#中Task.ContinueWith如何使用

Task.ContinueWith 方法是 Task 类的一个成员&#xff0c;它允许你为一个任务添加一个延续操作。这个延续操作会在任务完成时执行&#xff0c;无论是成功完成、发生异常还是被取消。你可以使用这个方法来执行一些清理工作&#xff0c;或者基于前一个任务的结果来启动另一个任务…

Java中的基本数据类型和引用类型存储在JVM中那个区域?

首先说明&#xff0c;"java中的基本数据类型一定存储在栈中的吗&#xff1f;”这句话肯定是错误的。 下面让我们一起来分析下原因&#xff1a; 基本数据类型是放在栈中还是放在堆中&#xff0c;这取决于基本类型在何处声明&#xff0c;下面对数据类型在内存中的存储问题…

第三季度中国游戏市场收入创历史新高;京东物流与淘宝天猫达成合作;YouTube 上线“用相机拍摄”标签....|网易数智日报

第三季度中国游戏市场收入917.66亿&#xff0c;创历史新高 中国音数协游戏工委今日发布了最新的 2024 年第三季度中国游戏产业季度报告。 数据显示&#xff0c;2024 年第三季度中国游戏市场收入 917.66 亿元&#xff0c;环比增长 22.96%&#xff0c;同比增长 8.95%。 中国音…

【Axure高保真原型】标签管理可视化驾驶舱长页面案例

今天和大家分享标签管理可视化驾驶舱长页面案例的原型模板&#xff0c;包括我的工作、通告消息、标签总体调用趋势、标签应用业务场景对比、标签使用排名、各个标签使用情况……具体效果可以点击下方视频观看或打开下方预览地址查看哦 【原型效果】 【Axure高保真原型】标签管…

信创服务器下连接kingbase并执行SQL的脚本

信创服务器下连接kingbase并执行SQL的脚本 .bash_profile Get the aliases and functions if [ -f ~/.bashrc ]; then. ~/.bashrc fiUser specific environment and startup programs PATH$PATH:/home/kingbase/Server/bin export PATH export LD_LIBRARY_PATH/home/kingba…