ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] ## IoC 与 DI 概念 ### IoC (反转控制):是一个概论 > 即把对象的调用权反转交给容器进行装配和管理 ### DI (依赖注入):是IoC的具体实现 > 对象之间依赖关系由容器在运行期决定,由容器动态的将依赖关系注入到对象之中 ## 简单对象注入 ### 构造方法注入 > `Controller`是由DI进行创建管理的,所以可以其构造函数上的参数会自动进行注入 ~~~ namespace App\Controller; use App\Service\UserService; class IndexController { /** * @var UserService */ private $userService; // 通过在构造函数的参数上声明参数类型完成自动注入 public function __construct(UserService $userService) { $this->userService = $userService; } public function index() { $id = 1; // 直接使用 return $this->userService->getInfoById($id); } } ~~~ ### 通过 @Inject 注解注入 ~~~ namespace App\Controller; use App\Service\UserService; use Hyperf\Di\Annotation\Inject; class IndexController { /** * 通过 `@Inject` 注解注入由 `@var` 注解声明的属性类型对象 * @Inject * @var UserService */ private $userService; public function index() { $id = 1; // 直接使用 return $this->userService->getInfoById($id); } } ~~~ ## 抽象对象注入 > 主要是最大限度的完成程序的解耦 > 1. 定义接口类 ~~~ namespace App\\Service; interface UserServiceInterface { public function getInfoById(int $id); } ~~~ > 2. `UserService`实现接口类 ~~~ namespace App\Service; class UserService implements UserServiceInterface { public function getInfoById(int $id) { // 我们假设存在一个 Info 实体 return (new Info())->fill($id); } } ~~~ > 3. 在`config/autoload/dependencies.php`内完成关系配置 ~~~ return [ \App\Service\UserServiceInterface::class => \App\Service\UserService::class ]; ~~~ > 4. Contoller注入接口,会自动根据配置进行注入 ~~~ namespace App\Controller; use App\Service\UserServiceInterface; use Hyperf\Di\Annotation\Inject; class IndexController { /** * @Inject * @var UserServiceInterface */ private $userService; public function index() { $id = 1; // 直接使用 return $this->userService->getInfoById($id); } } ~~~ ## 工厂对象注入 > `UserServiceInterface`的注入交给`UserServiceFactory`来创建 > 1. 创建工厂类生成`UserService`对象 ~~~ namespace App\Service; use Hyperf\Contract\ConfigInterface; use Psr\Container\ContainerInterface; class UserServiceFactory { // 实现一个 __invoke() 方法来完成对象的生产,方法参数会自动注入一个当前的容器实例 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')); } } ~~~ > 2. 创建`UserService`类,其中构造函数提供了一个参数 ~~~ namespace App\Service; class UserService implements UserServiceInterface { /** * @var bool */ private $enableCache; public function __construct(bool $enableCache) { // 接收值并储存于类属性中 $this->enableCache = $enableCache; } public function getInfoById(int $id) { return (new Info())->fill($id); } } ~~~ > 3. 在`config/autoload/dependencies.php`调整绑定关系 ~~~ return [ \App\Service\UserServiceInterface::class => \App\Service\UserServiceFactory::class ]; ~~~