[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
];
~~~