Skip to content

Commit

Permalink
更新文档
Browse files Browse the repository at this point in the history
  • Loading branch information
ueaner committed May 21, 2018
1 parent 6e56cfc commit c1f91d2
Showing 1 changed file with 112 additions and 72 deletions.
184 changes: 112 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
Soli Dependency Injection Container
------------------

当前项目参考 [Phalcon 框架的依赖注入与服务定位器]实现。
当前项目参考了 Phalcon 框架的[依赖注入与服务定位器] 和 Laravel 框架的[服务容器] 实现。

依赖注入容器的目的为了降低代码的耦合度,提高应用的可维护性。

把组件之间的依赖,转换为对容器的依赖,通过容器进行服务管理(创建、配置和定位)。
服务容器的目的为了降低代码的耦合度,提高应用的可维护性;是用于管理类依赖和执行依赖注入的工具。

[![Build Status](https://travis-ci.org/soliphp/di.svg?branch=master)](https://travis-ci.org/soliphp/di)
[![Coverage Status](https://coveralls.io/repos/github/soliphp/di/badge.svg?branch=master)](https://coveralls.io/github/soliphp/di?branch=master)
Expand All @@ -15,137 +13,179 @@ Soli Dependency Injection Container
## Table of Contents

* [安装](#安装)
* [使用](#使用)
* [注册服务](#注册服务)
* [使用匿名函数注册服务](#使用匿名函数注册服务)
* [使用对象实例注册服务](#使用对象实例注册服务)
* [使用类名注册服务](#使用类名注册服务)
* [使用数组注册服务](#使用数组注册服务)
* [获取服务](#获取服务)
* [先看一个简单的例子](#先看一个简单的例子)
* [注册服务](#注册服务)
* [类名](#类名)
* [类实例](#类实例)
* [闭包/匿名函数](#闭包匿名函数)
* [使用 $this 访问容器中的其他服务](#使用-this-访问容器中的其他服务)
* [注册接口到实现](#注册接口到实现)
* [共享(单例)服务](#共享单例服务)
* [注册共享服务](#注册共享服务)
* [获取共享服务](#获取共享服务)
* [静态方式访问容器](#静态方式访问容器)
* [获取服务](#获取服务)
* [get()](#get)
* [对象属性](#对象属性)
* [数组下标](#数组下标)
* [类名](#类名-1)
* [$this](#this)
* [静态方式访问容器](#静态方式访问容器)
* [示例](#示例)
* [API 参考](#api-参考)
* [测试](#测试)
* [License](#license)

## 安装

使用 `composer` 安装到你的项目
使用 `composer` 进行安装

composer require soliphp/di

## 使用
## 先看一个简单的例子

use Psr\Log\LoggerInterface;

class ExceptionHandler
{
/**
* 日志记录器
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;

public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}

/**
* 异常报告
*/
public function report(\Throwable $e)
{
$this->logger->error($e->getMessage());
}
}


异常处理类 `ExceptionHandler` 需要 `logger` 记录(报告)异常,
因此,我们需要`注入`实现了 `Psr\Log\LoggerInterface` 接口的类。
`logger` 的实现是要发短信、发邮件或进日志系统,这个 `ExceptionHandler`
是不关心的,所以我们可以轻易地将 `logger` 切换为另一个实现。
在为应用编写测试时,也可以轻松的模拟 `Psr\Log\LoggerInterface` 的实现。

容器中常用的四个方法,注册服务时的 `set/setShared` 方法和获取服务时的 `get/getShared` 方法。
## 注册服务

服务的注册阶段,仅仅是存储服务定义的格式,并不会调用服务的定义;
而在获取服务(即使用服务)时,对服务定义进行调用,得到服务定义的执行结果。
这样便实现了对服务的延迟加载,避免实例化请求中未用到的服务。
这样便实现了对`服务的延迟加载`,避免实例化请求中未用到的服务。

### 注册服务
以下 `$container` 变量均为 `Soli\Di\Container` 实例。

`服务提供者的格式`,可以是 `匿名函数、对象实例、类名或数组`

#### 使用匿名函数注册服务
### 类名

use Soli\Di\Container;

$container = new Container();

$container->set('someService', \SomeNamespace\SomeService::class);

### 类实例

$container->set('someService', new \SomeNamespace\SomeService());

### 闭包/匿名函数

// 注册服务,存储服务的定义
$container->set('someComponent', function () {
return new SomeComponent;
$container->set('someService', function () {
return new SomeService();
});

*使用 $this 访问容器中的其他服务*
#### 使用 $this 访问容器中的其他服务

`当使用匿名函数注册服务时,函数体内可以使用 $this 表示当前的 $container 容器对象实例
直接访问容器中的其他服务,便于服务之间进行交互。`
当使用匿名函数注册服务时,函数体内可以使用 `$this` 表示当前的 `$container` 容器类实例
直接访问容器中的其他服务,便于服务之间进行交互。

// 注册服务,存储服务的定义
$container->set('someService', function () {
// 此处的 $tihs 即是当前的 $container 容器对象实例
var_dump($this->getServices());

// 此处的 $tihs 即是当前的 $container 容器类实例
// 通过 $this 直接访问容器中的其他服务
var_dump($this->someComponent);
var_dump($this->otherService);
});

将在获取服务时,返回匿名函数的执行结果。
### 注册接口到实现

#### 使用对象实例注册服务
`注册接口到实现类`

$container->set('someComponent', new \SomeNamespace\SomeComponent());
$container->set('Database\AdapterInterface', 'Database\Adapter\Mysql');

将在获取服务时,返回对应的对象实例。
如果一个类需要处理后才会得到一个适用的实例,那么这里的实现就是一个匿名函数,
可以`注册接口到匿名函数`,注意匿名函数的返回实例即可:

#### 使用类名注册服务
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$container->set('someComponent', '\SomeNamespace\SomeComponent');
$container->set('Psr\Log\LoggerInterface', function () {
// create a log channel
$log = new Logger('name');
$log->pushHandler(new StreamHandler('/path/to/your.log', Logger::WARNING));

将在获取服务时,返回对应类名的实例化对象。
return $log;
});

#### 使用数组注册服务
### 共享(单例)服务

注:`注册数组类型数据作为服务,仅作为存储,不做任何解析和转换。`
共享服务意味着让服务以单例模式运行,之后的每次请求都会从容器取到同一个实例。
否则每次都会执行服务解析,返回新的服务实例。

$config = [
'application' => [
'viewsDir' => __DIR__ . '/views/',
'logsDir' => __DIR__ . '/logs/',
'cacheDir' => __DIR__ . '/cache/',
],
// ...
];
`默认使用 set() 注册的服务都为共享服务`

$container->set('config', $config);
如果需要`每次都使用新的实例`,则需要将第三个参数 `$shared 设置为 false`

将在获取服务时,返回注册的数组信息。
$container->set('newInstance', 'SomeNamespace\SomeService', false);

#### 获取服务
## 获取服务

获取服务时,调用服务定义,返回服务定义的执行结果:
获取服务时,调用服务定义,返回服务实例。

$service = $container->get('someService');
获取服务有多种方法:

### 共享(单例)服务
### get()

共享服务意味着让服务以单例模式运行,之后的每次请求都会从容器取到同一个实例。
使用 `get()` 方法获取服务:

#### 注册共享服务
$service = $container->get('someService');

与 set 方法对应,我们可以使用 setShared 方法,将服务注册为共享服务:
### 对象属性

$container->setShared('someService', <Some definition>);
使用访问`对象属性`的方式,获取服务:

#### 获取共享服务
$service = $container->someService;

### 数组下标

与 get 方法对应,我们可以使用 getShared 方法,获取共享服务
使用访问`数组下标`的方式,获取服务

$service = $container->getShared('someService');
$service = $container['someService'];

`当一个服务注册为非共享服务时,依然可以通过 getShared 方法获取共享实例。`
### 类名

对于类名无论是否已注册为服务,我们都可以直接通过容器获取到它的共享实例
对于`类名`无论是否已注册为服务,都可以直接通过容器获取到它的单例

$service = $container->getShared('\SomeNamespace\SomeComponent');
$service = $container->get('SomeNamespace\UnregisteredClass');

这对于我们日常开发中经常用到的单例模式,将格外的方便。

使用访问对象属性的方式,访问容器服务:
### $this

$service = $container->someService;
匿名函数注册服务时[使用 $this 访问容器中的其他服务](#使用-this-访问容器中的其他服务)

数组访问方式访问容器服务:
## 静态方式访问容器

$service = $container['someService'];
$container = Container::instance();

### 静态方式访问容器
$container->get('someService');

Container::instance()->getShared('someService');
这里需要注意一下,在调用 `Container::instance()` 之前,一定已经执行过 `new Container()` 实例化操作。

## 示例

Expand All @@ -171,8 +211,8 @@ Soli Dependency Injection Container

MIT Public License


[Phalcon 框架的依赖注入与服务定位器]: https://docs.phalconphp.com/en/latest/di
[依赖注入与服务定位器]: https://docs.phalconphp.com/en/latest/di
[服务容器]: https://laravel.com/docs/master/container
[API 参考]: http:https://soli-api.aboutc.net/Soli/Di.html
[examples]: examples
[Laravel 框架的服务提供者]: https://laravel.com/docs/5.4/providers

0 comments on commit c1f91d2

Please sign in to comment.