简单得容器:
class SomeComponent{ protected $_connection; public function setConnection($connection){ $this->_connection = $connection; } public function getConnection($connection){ return $this->_connection; } } 这个案例可以实现我们在外部注入到SomeComponent类中,不过这样不好得就是只能写一个实例,
class SomeComponent{ protected $_connection; public function setConnection($key, $connection){ $this->_connection[$key] = $connection; } public function getConnection($key){ if( isset( $this->_connection[$key] ) ){ return $this->_connection[$key] }else{ throw new Exception("class not exist", 1); } } } 这个例子可以实现多个类注入到里面,但是不好得就是得手动实例化类。
laravel中得依赖注入容器(里面主要用到得技术:反射,依赖注入,闭包):
//容器类装实例或提供实例的回调函数 class Container { //用于装提供实例的回调函数,真正的容器还会装实例等其他内容 //从而实现单例等高级功能 protected $bindings = []; //绑定接口和生成相应实例的回调函数 public function bind($abstract, $concrete=null, $shared=false) { //如果提供的参数不是回调函数,则产生默认的回调函数 if(!$concrete instanceof Closure) { $concrete = $this->getClosure($abstract, $concrete); } $this->bindings[$abstract] = compact('concrete', 'shared'); } //默认生成实例的回调函数 protected function getClosure($abstract, $concrete) { return function($c) use ($abstract, $concrete) { $method = ($abstract == $concrete) ? '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; } protected function isBuildable($concrete, $abstract) { return $concrete === $abstract || $concrete instanceof Closure; } //获取绑定的回调函数 protected function getConcrete($abstract) { if(!isset($this->bindings[$abstract])) { return $abstract; } return $this->bindings[$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($parameters) { $dependencies = []; foreach($parameters as $parameter) { $dependency = $parameter->getClass(); if(is_null($dependency)) { $dependencies[] = NULL; } else { $dependencies[] = $this->resolveClass($parameter); } } return (array)$dependencies; } protected function resolveClass(ReflectionParameter $parameter) { return $this->make($parameter->getClass()->name); } } 上面的代码就生成了一个容器,下面是如何使用容器
$app = new Container(); $app->bind("Pay", "Alipay");//Pay 为接口, Alipay 是 class Alipay $app->bind("tryToPayMyBill", "PayBill"); //tryToPayMyBill可以当做是Class PayBill 的服务别名 //通过字符解析,或得到了Class PayBill 的实例 $paybill = $app->make("tryToPayMyBill"); //因为之前已经把Pay 接口绑定为了 Alipay,所以调用pay 方法的话会显示 'pay bill by alipay ' $paybill->payMyBill(); 参考文章:链接地址
文章来源: PHP IOC容器