溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

ThinkPHP容器之容器是如何返回實(shí)例的

發(fā)布時(shí)間:2020-12-10 10:23:32 來源:億速云 閱讀:186 作者:小新 欄目:編程語言

這篇文章主要介紹ThinkPHP容器之容器是如何返回實(shí)例的,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

Container實(shí)例調(diào)用make方法

本文沒有太多文字解析,都在代碼注釋中說明了執(zhí)行過程。

代碼static::getInstance()返回了Container的實(shí)例后,就會(huì)去調(diào)用本類的make方法,接下來就是對(duì)make方法進(jìn)行詳解了。

ThinkPHP容器之容器是如何返回實(shí)例的在開始閱讀make方法里邊的源碼之前,我們需要先對(duì)幾個(gè)屬性進(jìn)行簡(jiǎn)單的梳理一下。

這四個(gè)屬性一定要有點(diǎn)印象,并且一定要區(qū)別instance和instances。

這倆個(gè)屬性一個(gè)是單例模式返回當(dāng)前類的實(shí)例,一個(gè)是容器中的所有的實(shí)例。

ThinkPHP容器之容器是如何返回實(shí)例的第一次執(zhí)行結(jié)果

   /**     * 創(chuàng)建類的實(shí)例     * @access public     * @param  string        $abstract       類名或者標(biāo)識(shí)     * @param  array|true    $vars           變量     * @param  bool          $newInstance    是否每次創(chuàng)建新的實(shí)例     * @return object     */    public function make($abstract, $vars = [], $newInstance = false)    {        // 判斷$vars這個(gè)變量是否為true        if (true === $vars) {            // 總是創(chuàng)建新的實(shí)例化對(duì)象            $newInstance = true;            $vars        = [];        }        // app  這里就是在容器別名里獲取傳遞過來的app    如果沒有則就是app        $abstract = isset($this->name[$abstract]) ? $this->name[$abstract] : $abstract;                // 從容器實(shí)例中獲取  如果存在則直接返回對(duì)應(yīng)的實(shí)例  也就是使用注冊(cè)樹模式        if (isset($this->instances[$abstract]) && !$newInstance) {            return $this->instances[$abstract];        }        // think\App 從容器標(biāo)識(shí)中獲取        if (isset($this->bind[$abstract])) {            // 將think\App 復(fù)制給$concrete變量            $concrete = $this->bind[$abstract];            // 用于代表匿名函數(shù)的類  判斷是不是閉包            if ($concrete instanceof Closure) {                $object = $this->invokeFunction($concrete, $vars);            } else {                // $this->name['app'] = think\App                $this->name[$abstract] = $concrete;                // 在執(zhí)行一次本類的make方法,也就是本方法                return $this->make($concrete, $vars, $newInstance);            }        } else {            $object = $this->invokeClass($abstract, $vars);        }        if (!$newInstance) {            $this->instances[$abstract] = $object;        }        return $object;    }

這是第二次執(zhí)行流程

    public function make($abstract, $vars = [], $newInstance = false)    {        // 判斷$vars這個(gè)變量是否為true        if (true === $vars) {            // 總是創(chuàng)建新的實(shí)例化對(duì)象            $newInstance = true;            $vars        = [];        }        // app  這里就是在容器別名里獲取傳遞過來的app    如果沒有則就是app        // 第二次執(zhí)行時(shí) $abstract = think\App        $abstract = isset($this->name[$abstract]) ? $this->name[$abstract] : $abstract;        // 從容器實(shí)例中獲取  如果存在則直接返回對(duì)應(yīng)的實(shí)例  也就是使用注冊(cè)樹模式        if (isset($this->instances[$abstract]) && !$newInstance) {            return $this->instances[$abstract];        }        // think\App 從容器標(biāo)識(shí)中獲取        // 第二次執(zhí)行$this->bind['think\App']不存在走else        if (isset($this->bind[$abstract])) {            // 將think\App 復(fù)制給$concrete變量            $concrete = $this->bind[$abstract];            // 用于代表匿名函數(shù)的類  判斷是不是閉包            if ($concrete instanceof Closure) {                $object = $this->invokeFunction($concrete, $vars);            } else {                // $this->name['app'] = think\App                $this->name[$abstract] = $concrete;                // 在執(zhí)行一次本類的make方法,也就是本方法                // think\App                return $this->make($concrete, $vars, $newInstance);            }        } else {            // think\App            $object = $this->invokeClass($abstract, $vars);        }        if (!$newInstance) {            // 把創(chuàng)建的容器存起來            //$this->instances['think\App'] = $object;            $this->instances[$abstract] = $object;        }        return $object;    }
public function invokeClass($class, $vars = [])    {        try {            /**             * ReflectionClass Object                (                [name] => think\App                )             */            // 這里就是之前文章提到的反射            $reflect = new ReflectionClass($class);            if ($reflect->hasMethod('__make')) {                $method = new ReflectionMethod($class, '__make');                if ($method->isPublic() && $method->isStatic()) {                    $args = $this->bindParams($method, $vars);                    return $method->invokeArgs(null, $args);                }            }            // 通過反射獲取think\App的構(gòu)造函數(shù)            $constructor = $reflect->getConstructor();            $args = $constructor ? $this->bindParams($constructor, $vars) : [];            // 從給出的參數(shù)創(chuàng)建一個(gè)新的類實(shí)例            return $reflect->newInstanceArgs($args);        } catch (ReflectionException $e) {            throw new ClassNotFoundException('class not exists: ' . $class, $class);        }    }

執(zhí)行流程圖

既然把代碼都理清楚了,這時(shí)來理一下執(zhí)行的流程圖可以看的更清晰。

以上是“ThinkPHP容器之容器是如何返回實(shí)例的”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI