详解Laravel服务容器的绑定与解析(3)

  实际上,当我们使用singleton,bind方法以及数组形式,(这三个方法是后面要介绍的绑定的方法),进行服务绑定的时候,如果绑定的服务形式,不是一个匿名函数,也会在laravel内部用一个匿名函数包装起来,这样的话, 不轮绑定什么内容,都能做到前面介绍的懒初始化的功能,这对于容器的性能是有好处的。这个可以从bind的源码中看到一些细节:

if (! $concrete instanceof Closure) {
  $concrete = $this->getClosure($abstract, $concrete);
}

看看bind的底层代码

public function bind($abstract, $concrete = null, $shared = false)

  第一个参数服务绑定名称,第二个参数服务绑定的结果(也就是闭包,得到实例),第三个参数就表示这个服务是否在多次解析的时候,始终返回第一次解析出的实例(也就是单例绑定singleton)。

  服务绑定还可以通过数组的方式:

app()['service'] = function(){
  return new Service();
};

绑定大概就这些,接下来看解析,也就是取出来用

$service= app()->make('service');

  这个方法接收两个参数,第一个是服务的绑定名称和服务绑定名称的别名,如果是别名,那么就会根据服务绑定名称的别名配置,找到最终的服务绑定名称,然后进行解析;第二个参数是一个数组,最终会传递给服务绑定产生的闭包。

看源码:

/**
 * Resolve the given type from the container.
 *
 * @param string $abstract
 * @param array $parameters
 * @return mixed
 */
public function make($abstract, array $parameters = [])
{
  return $this->resolve($abstract, $parameters);
}
/**
 * Resolve the given type from the container.
 *
 * @param string $abstract
 * @param array $parameters
 * @return mixed
 */
protected function resolve($abstract, $parameters = [])
{
  $abstract = $this->getAlias($abstract);
  $needsContextualBuild = ! empty($parameters) || ! is_null(
    $this->getContextualConcrete($abstract)
  );
  // If an instance of the type is currently being managed as a singleton we'll
  // just return an existing instance instead of instantiating new instances
  // so the developer can keep using the same objects instance every time.
  if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
    return $this->instances[$abstract];
  }
  $this->with[] = $parameters;
  $concrete = $this->getConcrete($abstract);
  // We're ready to instantiate an instance of the concrete type registered for
  // the binding. This will instantiate the types, as well as resolve any of
  // its "nested" dependencies recursively until all have gotten resolved.
  if ($this->isBuildable($concrete, $abstract)) {
    $object = $this->build($concrete);
  } else {
    $object = $this->make($concrete);
  }
  // If we defined any extenders for this type, we'll need to spin through them
  // and apply them to the object being built. This allows for the extension
  // of services, such as changing configuration or decorating the object.
  foreach ($this->getExtenders($abstract) as $extender) {
    $object = $extender($object, $this);
  }
  // If the requested type is registered as a singleton we'll want to cache off
  // the instances in "memory" so we can return it later without creating an
  // entirely new instance of an object on each subsequent request for it.
  if ($this->isShared($abstract) && ! $needsContextualBuild) {
    $this->instances[$abstract] = $object;
  }
  $this->fireResolvingCallbacks($abstract, $object);
  // Before returning, we will also set the resolved flag to "true" and pop off
  // the parameter overrides for this build. After those two things are done
  // we will be ready to return back the fully constructed class instance.
  $this->resolved[$abstract] = true;
  array_pop($this->with);
  return $object;
}
      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/5049.html