多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[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)