Laravel 框架 三种绑定 bind、singleton、instance 源码分析

laravel 框架采用IoC模式即(inversion of Controller)控制反转进行类的操作。将要使用的类提前绑定到容器中。今天我们讲解的不是IoC,主要通过laravel 源码分析三种绑定的区别,有利于大家对laravel框架有更进一步的了解。
一、instance 绑定

  首先我们来看一下instance方法的代码

public function instance($abstract, $instance)
{

//移除已经存在的抽象的别名
$this->removeAbstractAlias($abstract);

//检查是否已经存在该别名的绑定的对象
$isBound=$this->bound($abstract);
unset($this->aliases[$abstract]);

// We'll check to determine if this type has been bound before, and if it has
// we will fire the rebound callbacks registered with the container and it
// can be updated with consuming classes that have gotten resolved here.
$this->instances[$abstract] = $instance;

// 判断是否已经绑定
if ($isBound) {
    $this->rebound($abstract);
}

}

可以看到在instance方法中,首先移除已经存在的相同的别名,然后将对象存入$this->instance 数组中。然后完成了绑定。

二、bind 绑定

同样的,我们先贴出代码

public function bind($abstract, $concrete = null, $shared = false)
{
// If no concrete type was given, we will simply set the concrete type to the
// abstract type. After that, the concrete type to be registered as shared
// without being forced to state their classes in both of the parameters.

//移除旧的实例
$this->dropStaleInstances($abstract);
if (is_null($concrete)) {
    $concrete = $abstract;
}
// If the factory is not a Closure, it means it is just a class name which is
// bound into this container to the abstract type and we will just wrap it
// up inside its own Closure to give us more convenience when extending.
if (! $concrete instanceof Closure) {
    $concrete = $this->getClosure($abstract, $concrete);
}
// 创建一个包含变量与其值的数组。
//对每个参数,compact() 在当前的符号表中查找该变量名并将它添加到输出的数组中,变量名成为键名而变量的内容成为该键的值。简单说,它做的事和 extract() 正好相反。返回将所有变量添加进去后的数组。
$this->bindings[$abstract] = compact('concrete', 'shared');

// If the abstract type was already resolved in this container we'll fire the
// rebound listener so that any objects which have already gotten resolved
// can have their copy of the object updated via the listener callbacks.
//检查是否解析过 或则 已经存在所要绑定对象对应的实例
if ($this->resolved($abstract)) {
    $this->rebound($abstract);
}

}

使用bind 的形式如下:

$this->app->bind('HelpSpot\API', function ($app) {
return new HelpSpot\API($app->make('HttpClient'));
});

在bind 方法中 首先移除旧的实例,绑定的对象实例一般是放在闭包中,如果第二个参数不是闭包,是类名,会通过getClosure函数将类名封装进闭包中,然后在闭包中通过容器的make或build函数解析该类。绑定会将相应的闭包以及是否share 放进$this->bindings数组中。在解析的时候调用。
singleton 绑定

/**

  • Register a shared binding in the container.
  • 绑定到容器的对象只会被解析一次,之后的调用都返回相同的实例:
  • @param string|array $abstract
  • @param \Closure|string|null $concrete
  • @return void
    */
    public function singleton($abstract, $concrete = null)
    {
    $this->bind($abstract, $concrete, true);
    }

可以知道singleton 只是bind的一个调用。

这就是对laravel框架中三个绑定的源码分析。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 1
Summer

代码高亮有问题

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!