Skip to content

Latest commit

 

History

History
97 lines (81 loc) · 3.25 KB

dependency.md

File metadata and controls

97 lines (81 loc) · 3.25 KB

依赖解决

依赖解决是服务容器中最重要的一个功能之一。容器通过反射得到要实例化的类的依赖以后,调用resolveDependencies方法来实现 依赖解决。

//src/Illuminate/Container/Container.php

/**
 * Resolve all of the dependencies from the ReflectionParameters.
 *
 * @param  array  $dependencies
 * @return array
 */
protected function resolveDependencies(array $dependencies)
{
    $results = [];

    foreach ($dependencies as $dependency) {
        // If this dependency has a override for this particular build we will use
        // that instead as the value. Otherwise, we will continue with this run
        // of resolutions and let reflection attempt to determine the result.
        if ($this->hasParameterOverride($dependency)) {
            $results[] = $this->getParameterOverride($dependency);

            continue;
        }

        // If the class is null, it means the dependency is a string or some other
        // primitive type which we can not resolve since it is not a class and
        // we will just bomb out with an error since we have no-where to go.
        $results[] = is_null($dependency->getClass())
                        ? $this->resolvePrimitive($dependency)
                        : $this->resolveClass($dependency);
    }

    return $results;
}

$dependencies是一个数组,它包含了要实例化的类的构造函数中所有参数,它们的类型是\ReflectionParameter。 通过\ReflectionParameter,我们可以知道这个参数的类型是primitive还是class。如果它是primitive的话,那么就 调用resolvePrimitive,否则就调用resolveClass

//src/Illuminate/Container/Container.php

/**
 * Resolve a non-class hinted primitive dependency.
 *
 * @param  \ReflectionParameter  $parameter
 * @return mixed
 *
 * @throws \Illuminate\Contracts\Container\BindingResolutionException
 */
protected function resolvePrimitive(ReflectionParameter $parameter)
{
    if (! is_null($concrete = $this->getContextualConcrete('$'.$parameter->name))) {
        return $concrete instanceof Closure ? $concrete($this) : $concrete;
    }

    if ($parameter->isDefaultValueAvailable()) {
        return $parameter->getDefaultValue();
    }

    $this->unresolvablePrimitive($parameter);
}

/**
 * Resolve a class based dependency from the container.
 *
 * @param  \ReflectionParameter  $parameter
 * @return mixed
 *
 * @throws \Illuminate\Contracts\Container\BindingResolutionException
 */
protected function resolveClass(ReflectionParameter $parameter)
{
    try {
        return $this->make($parameter->getClass()->name);
    }

    // If we can not resolve the class instance, we will check to see if the value
    // is optional, and if it is we will return the optional parameter value as
    // the value of the dependency, similarly to how we do this with scalars.
    catch (BindingResolutionException $e) {
        if ($parameter->isOptional()) {
            return $parameter->getDefaultValue();
        }

        throw $e;
    }
}

对于primitive类型的值来说,如果没有默认值的情况下,容器是没法构建它的值。而对于class类型来说,容器直接以class类型的名称,通过 间接解析,将实例从容器中解析出来作为参数值。