204 IOC 仿照laravel实现一个最简容器 2
2016-10-25 23:40
393 查看
仿照laravel实现一个最简容器 2
一、闭包实现bind
由此我们实现了容器的核心功能<?php class Ioc{ protected $bindings = []; function bind($abstract,$concrete = null,$shared = 0){ echo "step bind abstract : [$abstract] <br/>"; if (!$concrete instanceof Closure){ $concrete = $this->getClosure($abstract,$concrete); } // $this->bindings[$abstract] = compact($concrete,$share); $this->bindings[$abstract] = compact('concrete','shared'); } function getClosure($abstract,$concrete){ return function ($c) use ($abstract,$concrete){ echo "step getClosure abstract : [$abstract] , concrete : [$concrete] <br/>"; $method = ($abstract == $concrete) ? 'build' : 'make'; return $c->$method($concrete); }; } function make($abstract){ $concrete = $this->getConcrete($abstract); echo "step make abstract : [$abstract] , abstract : [$abstract] <br/>"; if ($this->isBuildable($concrete,$abstract)){ $object = $this->build($concrete); } else { $object = $this->make($concrete); } return $object; } public function getConcrete($abstract){ echo "step getConcrete abstract : [$abstract] <br/>"; if (isset($this->bindings[$abstract])){ // var_dump($this->bindings[$abstract]['concrete']); // 这里会返回bind的时候绑定的闭包,但是闭包未被调用 return $this->bindings[$abstract]['concrete']; } return $abstract; } public function isBuildable($concrete,$abstract){ return $abstract === $concrete || $concrete instanceof Closure; } function build($concrete){ if ($concrete instanceof Closure){ echo "step build <br/>"; } else { echo "step build concrete : [$concrete] <br/>"; } if ($concrete instanceof Closure){ //到这里getClosure 才第一次被执行 return $concrete($this); } //下面的情况应该是对应 $abstract == $concrete $reflector = new ReflectionClass($concrete); if (! $reflector->isInstantiable()){ echo $message = "target [$concrete] is not isInstantiable"; } $constructor = $reflector->getConstructor(); if (is_null($constructor)){ return new $concrete; } $dependencies = $constructor->getParameters(); $instances = $this->getDependencies($dependencies); return $reflector->newInstanceArgs($instances); } function getDependencies($parameters){ $dependencies = []; foreach ($parameters as $parameter) { $dependency = $parameter->getClass(); if (is_null($dependency)){ $dependencies[] = null; } else { $dependencies[] = $this->resolveClass($parameter); } } return (array)$dependencies; } function resolveClass( ReflectionParameter $parameter){ return $this->make($parameter->getClass()->name); } } interface Tool{ function go(); } class Train implements Tool{ function go(){ echo "drive to tibet"; } } $app = new ioc(); $app->bind('tool','Train'); $tool = $app->make('tool');
二、分析下执行流程
上面的代码执行之后会得到如下结果step bind abstract : [tool] step getConcrete abstract : [tool] step make abstract : [tool] , abstract : [tool] step build step getClosure abstract : [tool] , concrete : [Train] step getConcrete abstract : [Train] step make abstract : [Train] , abstract : [Train] step build concrete : [Train]
1.首先是Bind()
我们bind的是字符串,所以会调用getClosure,
return function ($c) use ($abstract,$concrete){ $method = ($abstract == $concrete) ? 'build' : 'make'; return $c->$method($concrete); };
但是
getClosure返回的是一个闭包,闭包函数不会被立刻调用,所以我们暂时不知道
$c这个参数是什么,但是我们知道
$abstrac,
$concrete分别对应
'tool'和
'Train'这两个字符串
2.然后是第一次make()
这是第一次调用make(),参数的值应该是
'tool',
getConcrete()会返回之前
bind()的那个闭包,此处闭包仍然没有被执行。
isBuildable()返回
true,于是我们来到第一次
build(),传入的参数是之前
bind()的那个闭包,
if ($concrete instanceof Closure)会返回
true,于是执行了这一句
return $concrete($this);
闭包终于被执行了,还记得第一步中
bind()的那几个参数吗,闭包中的
return $c->$method($concrete);
就等效于
return $this->make('Train');
3.之后就是第二次make()
这次就简单了,getConcrete()会返回
'Train',
isBuildable()返回
true,于是我们来到第二次
build(),传入的参数是
'Train'
4.使用反射来搞定依赖注入
在build()中可以看到,因为
Train这个类没有构造函数,所以直接
new了一个出来并返回,如果
Train这个类有构造函数,它会根据构造函数中的参数去容器中再次
make()并注入到
Train里面。
相关文章推荐
- 202 Ioc 仿照laravel实现一个最简的ioc容器
- 仿照spring-boot实现一个简单的ioc容器(二)
- 仿照spring-boot实现一个简单的ioc容器(一)
- IoC原理-使用反射/Emit来实现一个最简单的IoC容器
- 深入理解Spring--动手实现一个简单的SpringIOC容器
- 【最简单IOC容器实现】实现一个最简单的IOC容器
- Spring实现一个简单的SpringIOC容器
- 1000行代码读懂Spring(一)- 实现一个基本的IoC容器
- 1000行代码读懂Spring- 实现一个基本的IoC容器
- 如何设计并实现一个ioc容器(转载)
- 简单实现一个laravelapp容器绑定实例
- 【最简单IOC容器实现】实现一个最简单的IOC容器
- 揣摩实现一个ioc容器需要做的事情
- 1000行代码读懂Spring(一)- 实现一个基本的IoC容器
- 深入理解Spring--动手实现一个简单的SpringIOC容器-注解版
- IoC原理-使用反射/Emit来实现一个最简单的IoC容器
- 自己实现一个IOC(控制翻转,DI依赖注入)容器
- 实现一个简易IOC容器
- 用java的spring实现一个简单的IOC容器示例代码
- 写一个自己的Spring框架——简单实现IoC容器功能