[TOC]
# 容器类
~~~
<?php
class Container
{
//用于提供实例的回调函数,真正的容器还会装实例等其他内容.从而实现单列等高级功能
public $binding = [];
//绑定接口和生成相应实例的回调函数
public function bind($abstract, $concrete = null, $shared = false)
{
if (!$concrete instanceof Closure) {
//如果提供的参数不是回调函数则产生默认的回调函数
$concrete = $this->getClosure($abstract, $concrete);
}
$this->binding[$abstract] = compact('concrete', 'shared');
}
//默认生成的实例的回调函数
protected function getClosure($abstract, $concrete)
{
//生成实例的回调函数,$c一般为IOC容器对象,在调用回调生成实例时提供
//即build函数中的$concrete($this)
return function ($c) use ($abstract, $concrete) {
$method = ($abstract == $concrete) ? 'build' : 'make';
//调用的是容器的build或make方法生成的实例
return $c->$method($concrete);
};
}
//生成实例对象,首先要解决接口和要实例化类之间的依赖关系
public function make($abstract)
{
$concrete = $this->getConcrete($abstract);
if ($this->isBuildable($concrete, $abstract)) {
$object = $this->build($concrete);
} else {
$object = $this->make($concrete);
}
return $object;
}
public function isBuildable($concrete, $abstract)
{
return $concrete === $abstract || $concrete instanceof Closure;
}
//获取绑定的回调函数
protected function getConcrete($abstract)
{
if (!isset($this->binding[$abstract])) {
return $abstract;
}
return $this->binding[$abstract]['concrete'];
}
//实例化对象
public function build($concrete) {
if($concrete instanceof Closure) {
return $concrete($this);
}
//反射...
$reflector = new ReflectionClass($concrete);
if(!$reflector->isInstantiable()) {
echo $message = "Target [$concrete] is not instantiable";
}
//获取要实例化对象的构造函数
$constructor = $reflector->getConstructor();
//没有定义构造函数,只有默认的构造函数,说明构造函数参数个数为空
if(is_null($constructor)) {
return new $concrete;
}
//获取构造函数所需要的所有参数
$dependencies = $constructor->getParameters();
$instances = $this->getDependencies($dependencies);
//从给出的数组参数在中实例化对象
return $reflector->newInstanceArgs($instances);
}
/**
* 获取构建类所需要的所有依赖,级构造函数所需要的参数 ,
*/
protected function getDependencies($paramters) {
$dependencies = [];
foreach ($paramters as $paramter) {
//获取到参数名称.
$dep = $paramter->getClass();
if(is_null($dep)){
$dependencies = null;
}else{
$dependencies[] = $this->resolveClass($paramter);
}
}
return (array)$dependencies;
}
/**
* 实例化 构造函数中所需要的参数.
*/
protected function resolveClass(ReflectionParameter $parameter) {
$name = $parameter->getClass()->name;
return $this->make($name);
}
}
~~~
# 测试类
~~~
<?php
include './Container.php';
interface TrafficTool
{
public function go();
}
class Train implements TrafficTool
{
public function go()
{
echo "train....";
}
}
class Leg implements TrafficTool
{
public function go()
{
echo "leg..";
}
}
class Traveller
{
/**
* @var Leg|null|Train
* 旅行工具
*/
protected $_trafficTool;
public function __construct(TrafficTool$trafficTool)
{
$this->_trafficTool = $trafficTool;
}
public function visitTibet()
{
$this->_trafficTool->go();
}
}
//实例化IoC容器
$app = new Container();
//绑定某一功能到IoC
$app->bind('TrafficTool', 'Train');
$app->bind('travellerA', 'Traveller');
// 实例化对象
$tra = $app->make('travellerA');
$tra->visitTibet();
~~~
# 源码解析
在laravel框架中,服务容器是通过 `Illuminate\Container\Container` 类来实现的,其实现原理和上面相同,这里给出容器类的工作图
服务绑定有时也称为服务注册,在全文两者意义相同,只是对不同上下文环境某种说法更加贴切而已
服务容器工作示意图
![](https://box.kancloud.cn/c5ce096b11c288d589fde9c526ab395b_649x237.png)
![](https://box.kancloud.cn/d3eeae9a093cca23a2adfcbe3480011c_334x147.png)
服务容器类中定义了两个用于管理服务的属性,分别是`$bindings`和`$instance`,其中`$bindings`用于存储提供服务的回调函数,而`$instances`用于存储程序中的共享实例,也可以称为单例
![](https://box.kancloud.cn/cd73cb51796bcc33a96de3e7d5685a37_353x74.png)
![](https://box.kancloud.cn/a9b87639573738ad4cdd719444a7709c_769x835.png)
这几个函数实现了laravel框架的服务容器的服务绑定功能.主要是由bind()函数实现的
singleton()函数实现的是单例绑定,即程序中如果没有服务名称对应的实例对象,则通过服务容器实例化一个后进行记录,如果在后续的程序还需要同名的服务时则返回先前创建的服务实例对象.该函数相当于bind()函数的一个特例,即参数`$shared`值为true的情况
![](https://box.kancloud.cn/7a7202610995a1dec4385c493b938e30_777x126.png)
![](https://box.kancloud.cn/3f260049805385bf83025177f5baa414_759x37.png)
![](https://box.kancloud.cn/f7f05709fa33dbc502b4bcb120afc438_650x621.png)
![](https://box.kancloud.cn/36988a0df63ce90b8946155bb3289ab0_776x463.png)
![](https://box.kancloud.cn/37493fe6e931fd69566fe99aac83acf9_631x251.png)
![](https://box.kancloud.cn/cc89b0071333e6d477c859c29ab414c6_786x621.png)
![](https://box.kancloud.cn/daf1060c1d8a3b432bc0bcf339703fd6_539x253.png)
![](https://box.kancloud.cn/19986724e324dd8c0c296ff8345ad274_765x920.png)
![](https://box.kancloud.cn/075487d69ae0c187338bfa0fa82ad995_647x202.png)
![](https://box.kancloud.cn/9276bb7190865a8c11a9983a771e0b0e_774x550.png)
- 书列表
- laravel框架关键技术
- 第一章 组件化开发与composer使用
- 简介
- composer
- 添加路由组件
- 添加控制器模块
- 添加模型组件
- 添加视图组件
- 第三章 laravel框架中常用的php语法
- 匿名函数
- 文件包含
- 魔术方法
- 魔术常量
- 反射
- 后期静态绑定
- traits
- 第四章 laravel框架中使用的HTTP协议基础
- HTTP协议
- 数据库
- 数据迁移
- 第六章 laravel框架中的设计模式
- IOC模式
- php核心技术与最佳实践
- 第一章面向对象核心
- 反射
- 简单ORM
- 异常和错误
- 接口
- 第二章,面向对象设计
- 设计原则
- 单一职责
- 接口隔离
- 开放封闭
- 替换原则
- 依赖倒置
- linux是怎么写的呢?
- 第三章 正则表达
- 认识正则
- 第四章 php网络技术应用
- HTTP协议详解
- php和http相关函数
- 垃圾信息防御措施
- 现代操作系统
- 引论
- sql必知必会
- 限制结果
- 按位置排序
- where求职顺序
- IN操作符
- like
- 函数
- group by
- 组合查询
- 插入检索出的数据
- 视图
- 高性能mysql
- 第一章节 mysql架构与历史
- mysql架构逻辑图
- 连接与管理
- 优化与运行
- 读写锁
- 锁粒度
- 表锁(table lock)
- 行级锁(row lock)
- ACID
- 隔离级别
- 死锁
- 隐式和显式锁定
- 多版本并发控制
- Innodb概览
- 第四章节 Schema与数据类型优化
- 选择优化的数据类型
- 日期和时间类型
- 标识列
- 特殊类型数据
- 表设计中的缺陷
- 范式
- 计数器表
- 第五章 创建高性能索引
- 索引基础
- 索引类型
- 索引的优点
- 高性能索引策略
- 选择合适的索引列顺序
- 聚簇索引
- 顺序的主键什么时候会造成更坏的后果
- 覆盖索引
- 使用索引扫描来做排序
- 压缩索引
- 冗余和重复索引
- 索引和锁
- 支持多种过滤条件
- 什么是范围条件
- 优化排序
- 维护索引和表
- 表损坏
- 减少索引和数据的碎片
- 第六章 查询性能优化
- 扫描的行数和访问类型
- 重构查询方式
- 查询执行的基础
- 重构-改善既有代码设计
- 第一章-重构
- 什么是重构
- 第一个案列
- 重构第一步
- 王垠博客
- 多态取代价格相关逻辑