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