laravel服务容器的实现原理是什么

laravel 服务容器的实现原理是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

laravel 服务容器的实现原理是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

什么是服务容器

成都创新互联网站建设提供从项目策划、软件开发,软件安全维护、网站优化(SEO)、网站分析、效果评估等整套的建站服务,主营业务为成都网站设计、成都做网站,重庆APP开发公司以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。成都创新互联深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

服务容器是用来管理类依赖与运行依赖注入的工具。Laravel框架中就是使用服务容器来实现 ** 控制反转 ** 和 ** 依赖注入 **。

什么是控制反转(IoC)和依赖注入(DI)控制反转(IoC) 就是说把创建对象的** 控制权 进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,也就是 

Laravel ** 中的容器。

依赖注入(DI)则是帮助容器实现在运行中动态的为对象提供提依赖的资源。

概念容易不太容易让人理解,举个栗子:

//我们构建一个人的类和一个狗的类 class People{    public $dog = null;    public function __construct()    {        $this->dog = new Dog();    }    public function putDog(){        return $this->dog->dogCall();    }}class Dog{    public function dogCall(){        return '汪汪汪';    }} ``` 这个人在遛狗,突然遇到了死对头,他于是放狗咬人
$people = new People();
$people->putDog();
在这个操作中,people类要执行 putDog() 这个方法,需要依赖Dog类,一般我们像上面一样,在people中利用构造函数来添加这个Dog依赖。如果使用控制反转 依赖注入则是这个样子
class People
{

public $dog = null;

public function __construct(Dog $Dog){    $this->dog = $dog;}public function putDog(){    return $this->dog->dogCall();}

}

People类通过构造参数声明自己需要的 依赖类,由容器自动注入。这样就实现了程序的有效解耦,好处在这就不多说了。## Laravel容器依赖注入的实现###### 实现原理需要了解的知识点:> 闭包(匿名函数):匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数> 反射:PHP 5 以上版本具有完整的反射 API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。 此外,反射 API 提供了方法来取出函数、类和方法中的文档注释###### 理解了闭包和反射的基本用法我们来看Laravel中是怎么实现容器的,下面代码是我对laravel框架容器部分代码的简化核心版:
lass Container
{
/**
* 容器绑定,用来装提供的实例或者 提供实例的回调函数
* @var array
*/

public $building = [];

/** * 注册一个绑定到容器 */public function bind($abstract, $concrete = null, $shared = false){    if(is_null($concrete)){        $concrete = $abstract;    }    if(!$concrete instanceOf Closure){        $concrete = $this->getClosure($abstract, $concrete);    }    $this->building[$abstract] =  compact("concrete", "shared");}//注册一个共享的绑定 单例public function singleton($abstract, $concrete, $shared = true){    $this->bind($abstract, $concrete, $shared);}/** * 默认生成实例的回调闭包 * * @param $abstract * @param $concrete * @return Closure */public 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;}/** * 获取绑定的回调函数 */public function getConcrete($abstract){    if(! isset($this->building[$abstract])){        return $abstract;    }    return $this->building[$abstract]['concrete'];}/** * 判断 是否 可以创建服务实体 */public function isBuildable($concrete, $abstract){    return $concrete === $abstract || $concrete instanceof Closure;}/** * 根据实例具体名称实例具体对象 */public function build($concrete){    if($concrete instanceof Closure){        return $concrete($this);    }    //创建反射对象    $reflector = new ReflectionClass($concrete);    if( ! $reflector->isInstantiable()){        //抛出异常        throw new \Exception('无法实例化');    }    $constructor = $reflector->getConstructor();    if(is_null($constructor)){        return new $concrete;    }    $dependencies = $constructor->getParameters();    $instance = $this->getDependencies($dependencies);    return $reflector->newInstanceArgs($instance);}//通过反射解决参数依赖public function getDependencies(array $dependencies){    $results = [];    foreach( $dependencies as $dependency ){        $results[] = is_null($dependency->getClass())            ?$this->resolvedNonClass($dependency)            :$this->resolvedClass($dependency);    }    return $results;}//解决一个没有类型提示依赖public function resolvedNonClass(ReflectionParameter $parameter){    if($parameter->isDefaultValueAvailable()){        return $parameter->getDefaultValue();    }    throw new \Exception('出错');}//通过容器解决依赖public function resolvedClass(ReflectionParameter $parameter){    return $this->make($parameter->getClass()->name);}
}

```

容器的工作流程
接着上面遛狗的例子:
//实例化容器类 $app = new Container(); //向容器中填充Dog $app->bind('Dog','App\Dog'); //填充People $app->bind('People', 'App\People'); //通过容器实现依赖注入,完成类的实例化; $people = $app->make('People'); //调用方法 echo $people->putDog();上面示例中我们先实例化容器类,然后使用bind()方法 绑定接口和 生成相应的实例的闭包函数。然后使用make() 函数生成实例对象,在make()中会调用 isBuildable($concrete, $abstract) 来判断 给定的服务实体($concrete参数)是否可以创建,可以创建 就会调用 build($concrete) 函数 ,build($concrete)函数会判断传的参数是 是** 闭包 还是

 具体类名 **,如果是闭包则直接运行,如果是具体类名的话,则通过反射获取该类的构造函数所需的依赖,完成实例化。
** 重点理解 下面这几个函数中 反射的用法,应该就很好理解了 **

build($concrete) getDependencies(array $dependencies) resolvedNonClass(ReflectionParameter $parameter) resolvedClass(ReflectionParameter $parameter)


本文名称:laravel服务容器的实现原理是什么
文章链接:http://ybzwz.com/article/copoi.html