Laravel (5.5.33) 加载过程---make方法(四)

    /**
     * Resolve the given type from the container.
     *
     * @param  string  $abstract
     * @return mixed
     */
    public function make($abstract)
    {
        return $this->resolve($abstract);
    }

 


 

make函数的大致执行流程

 


 

其中resolve源码的说明

 

  /**
     * Resolve the given type from the container.
     *
     * @param  string  $abstract
     * @param  array  $parameters
     * @return mixed
     */
    protected function resolve($abstract, $parameters = [])
    {
        /**
         * 别名转换 
         */
        $abstract = $this->getAlias($abstract);

        /**
         * 如果参数不为空  或者给定的别名存在存在contextual中 则$needsContextualBuild 为true
         */
        $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.
        /**
         * 如果是给定的别名是容器类别名 
         * 如果是application中的  $this->instance('app', $this) 时候instances数组中不存在 app
         * app container  并且不需要build 则返回容器
         */
        if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
            return $this->instances[$abstract];
        }

        /**
         * 保存参数到with数组中
         */
        $this->with[] = $parameters;

        /**
         * 如果contextual 中存在别名信息 返回对于信息的值
         * 如果bindings   中存在别名信息 返回对于信息中的concrete键的值
         * 如果上述都不成立 返回别名
         */
        $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.
        /**
         * 如果$concrete 和$abstract相同  或者$concrete是一个匿名函数 条件成立
         */
        if ($this->isBuildable($concrete, $abstract)) {
            /**
             * 实例化$concrete 代码的类
             */
            $object = $this->build($concrete);
        } else {
            /**
             * 重新执行make函数
             */
            $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.
        /**
         * 获取extenders 中注册该别名对于的方法数组 逐个执行
         */
        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.
        /**
         * 判断bindings或者instances中是否已经存在该别名信息 判断$needsContextualBuild值
         */
        if ($this->isShared($abstract) && ! $needsContextualBuild) {
            $this->instances[$abstract] = $object;
        }

        /**
         * 执行全局注册的函数事件globalResolvingCallbacks  该函数注册的事件 resolvingCallbacks 
         * 完成实例化调用的全局事件globalAfterResolvingCallbacks  已经改函数实例化完成后调用的事件afterResolvingCallbacks
         */
        $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;
    }

 


 

其中关键的实例化返回build函数说明

    /**
     * 实例化一个对象
     * @param unknown $concrete
     * @return unknown|void|object
     */
    public function build($concrete)
    {
        // If the concrete type is actually a Closure, we will just execute it and
        // hand back the results of the functions, which allows functions to be
        // used as resolvers for more fine-tuned resolution of these objects.
        /**
         * 如果是匿名函数  
         */
        if ($concrete instanceof Closure) {
            return $concrete($this, $this->getLastParameterOverride());
        }

        /**
         * @link http://php.net/manual/zh/reflectionclass.construct.php
         * @return ReflectionClass $reflector
         */
        $reflector = new ReflectionClass($concrete);
        

        // If the type is not instantiable, the developer is attempting to resolve
        // an abstract type such as an Interface of Abstract Class and there is
        // no binding registered for the abstractions so we need to bail out.
        /**
         * @link http://php.net/manual/zh/reflectionclass.isinstantiable.php
         * 检查这个类是否可实例化  如果不能实例化 报错
         */
        if (! $reflector->isInstantiable()) {
            return $this->notInstantiable($concrete);
        }

        /**
         * 添加记录
         */
        $this->buildStack[] = $concrete;

        /**
         * 获取已反射的类的构造函数
         * @link http://php.net/manual/zh/reflectionclass.getconstructor.php
         * @return ReflectionMethod $constructor
         */
        $constructor = $reflector->getConstructor();

        // If there are no constructors, that means there are no dependencies then
        // we can just resolve the instances of the objects right away, without
        // resolving any other types or dependencies out of these containers.
        /**
         * 获取失败 弹出buildStack数据 返回一个实力
         */
        if (is_null($constructor)) {
            array_pop($this->buildStack);
            
            return new $concrete;
        }

        /**
         * 通过 ReflectionParameter 数组返回参数列表
         * @link http://php.net/manual/zh/reflectionfunctionabstract.getparameters.php
         * @var ReflectionParameter  $dependencies
         */
        $dependencies = $constructor->getParameters();

        // Once we have all the constructor's parameters we can create each of the
        // dependency instances and then use the reflection instances to make a
        // new instance of this class, injecting the created dependencies in.
        /**
         * 返回类中的属性和对应的值
         * @var array $instances
         */
        $instances = $this->resolveDependencies(
            $dependencies
        );

        /**
         * 弹出buildStack数据
         */
        array_pop($this->buildStack);

        /**
         * @link http://php.net/manual/zh/reflectionclass.newinstanceargs.php
         * 创建一个类的新实例,给出的参数将传递到类的构造函数
         * 
         * 给类中的属性赋值
         */
        return $reflector->newInstanceArgs($instances);
    }

 

通过resolveDependencies 获取类中属性的默认值  通过如果属性是一个匿名函数 则执行匿名函数  如果是一个类  值实例化类

/**
     * 返回对于属性的值  
     * @param array $dependencies
     * @return mixed[]|\Closure[]|unknown[]
     */
    protected function resolveDependencies(array $dependencies)
    {
        $results = [];

        /**
         * @var ReflectionParameter  $dependency
         */
        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.
            /**
             * @link http://php.net/manual/zh/reflectionparameter.getclass.php
             * @var ReflectionClass $class
             * 
             * 若该参数为对象,返回该对象的类名
             * 如果不是一点对象 使用 resolvePrimitive方法
             * 如果是一个对象对象信息 创建一个该对象  解决依赖问题
             */
            $results[] = is_null($class = $dependency->getClass())
                            ? $this->resolvePrimitive($dependency)
                            : $this->resolveClass($dependency);
        }

        return $results;
    }

 

如果是一个配置的匿名函数  则通过resolvePrimitive返回执行该匿名函数  返回

/**
     * 如果是一个匿名对象 执行匿名对象  返回执行结果
     * 如果是一个默认值 则返回默认值
     * 如果不存在默认值 则报错
     */
    protected function resolvePrimitive(ReflectionParameter $parameter)
    {
        /**查询给定的别名 查询contextual 中是否存在信息 如果存在返回 如果是抽象类别名 游离抽象类数组 查询对于的别名是否存在contextual 中 存在返回
         * 如果是一个匿名函数  值执行匿名函数 返回结果 如果不是你们函数 返回contextual中对于的值
         */
        if (! is_null($concrete = $this->getContextualConcrete('$'.$parameter->name))) {
            return $concrete instanceof Closure ? $concrete($this) : $concrete;
        }

        /**
         * @link http://php.net/manual/zh/reflectionparameter.isdefaultvalueavailable.php
         * 查看是否存在默认值
         */
        if ($parameter->isDefaultValueAvailable()) {
            return $parameter->getDefaultValue();
        }

        /**
         * 报错
         */
        $this->unresolvablePrimitive($parameter);
    }

如果该属性是一个类  则执行resolveClass 实例化该类

    /**
     * 实例化对于的类
     * @param ReflectionParameter $parameter
     * @throws BindingResolutionException
     * @return mixed|unknown|mixed
     */
    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;
        }
    }

 

posted on 2018-02-20 17:01  Sunlight1992  阅读(193)  评论(0编辑  收藏  举报

导航