>PHP 프레임워크 >ThinkPHP >ThinkPHP 컨테이너는 어떻게 인스턴스를 반환합니까?

ThinkPHP 컨테이너는 어떻게 인스턴스를 반환합니까?

咔咔
咔咔원래의
2020-10-12 12:51:251370검색
"

이전 글에서는 컨테이너 클래스를 간략하게 정리했고, 다음 단계는 그 세부 사항 중 하나에 대한 심층 분석을 진행하는 것입니다.

"

컨테이너 인스턴스는 make 메소드를 호출합니다.

이 글에는 내용이 많지 않습니다. 텍스트 분석은 코드 주석에서 실행 과정을 설명합니다.

Codestatic::getInstance()Container 인스턴스를 반환한 후 이 클래스의 make 메소드를 호출합니다. 다음 단계는 make 메소드를 자세히 설명하는 것입니다.

make 메소드의 소스 코드를 읽기 전에 몇 가지 속성을 간략하게 정리해야 합니다.

이 네 가지 속성은 어느 정도 인상적이어야 하며, 인스턴스와 인스턴스가 구별되어야 합니다.

이 두 속성 중 하나는 현재 클래스의 인스턴스를 반환하는 싱글톤 모드이고, 다른 하나는 컨테이너의 모든 인스턴스입니다.

첫 번째 실행 결과

<span style="display: block; background: url(https://my-wechat.mdnice.com/point.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #282c34; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #282c34; border-radius: 5px;">   <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">/**<br/>     * 创建类的实例<br/>     * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@access</span> public<br/>     * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@param</span>  string        $abstract       类名或者标识<br/>     * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@param</span>  array|true    $vars           变量<br/>     * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@param</span>  bool          $newInstance    是否每次创建新的实例<br/>     * <span class="hljs-doctag" style="color: #c678dd; line-height: 26px;">@return</span> object<br/>     */</span><br/>    <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">public</span> <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">function</span> <span class="hljs-title" style="color: #61aeee; line-height: 26px;">make</span><span class="hljs-params" style="line-height: 26px;">($abstract, $vars = [], $newInstance = false)</span><br/>    </span>{<br/>        <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 判断$vars这个变量是否为true</span><br/>        <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">true</span> === $vars) {<br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 总是创建新的实例化对象</span><br/>            $newInstance = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">true</span>;<br/>            $vars        = [];<br/>        }<br/><br/>        <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// app  这里就是在容器别名里获取传递过来的app    如果没有则就是app</span><br/>        $abstract = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->name[$abstract]) ? <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->name[$abstract] : $abstract;<br/>        <br/>        <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 从容器实例中获取  如果存在则直接返回对应的实例  也就是使用注册树模式</span><br/>        <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->instances[$abstract]) && !$newInstance) {<br/>            <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->instances[$abstract];<br/>        }<br/><br/>        <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// think\App 从容器标识中获取</span><br/>        <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bind[$abstract])) {<br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 将think\App 复制给$concrete变量</span><br/>            $concrete = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bind[$abstract];<br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 用于代表匿名函数的类  判断是不是闭包</span><br/>            <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> ($concrete <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">instanceof</span> Closure) {<br/>                $object = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->invokeFunction($concrete, $vars);<br/>            } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">else</span> {<br/>                <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// $this->name[&#39;app&#39;] = think\App</span><br/>                <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->name[$abstract] = $concrete;<br/>                <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 在执行一次本类的make方法,也就是本方法</span><br/>                <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->make($concrete, $vars, $newInstance);<br/>            }<br/>        } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">else</span> {<br/>            $object = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->invokeClass($abstract, $vars);<br/>        }<br/><br/>        <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (!$newInstance) {<br/>            <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->instances[$abstract] = $object;<br/>        }<br/><br/>        <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> $object;<br/>    }<br/></code>

두 번째 실행 과정입니다

<span style="display: block; background: url(https://my-wechat.mdnice.com/point.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #282c34; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #282c34; border-radius: 5px;">    <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">public</span> <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">function</span> <span class="hljs-title" style="color: #61aeee; line-height: 26px;">make</span><span class="hljs-params" style="line-height: 26px;">($abstract, $vars = [], $newInstance = false)</span><br/>    </span>{<br/>        <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 判断$vars这个变量是否为true</span><br/>        <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">true</span> === $vars) {<br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 总是创建新的实例化对象</span><br/>            $newInstance = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">true</span>;<br/>            $vars        = [];<br/>        }<br/><br/>        <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// app  这里就是在容器别名里获取传递过来的app    如果没有则就是app</span><br/>        <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 第二次执行时 $abstract = think\App</span><br/>        $abstract = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->name[$abstract]) ? <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->name[$abstract] : $abstract;<br/><br/>        <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 从容器实例中获取  如果存在则直接返回对应的实例  也就是使用注册树模式</span><br/>        <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->instances[$abstract]) && !$newInstance) {<br/>            <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->instances[$abstract];<br/>        }<br/><br/>        <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// think\App 从容器标识中获取</span><br/>        <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 第二次执行$this->bind[&#39;think\App&#39;]不存在走else</span><br/>        <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">isset</span>(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bind[$abstract])) {<br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 将think\App 复制给$concrete变量</span><br/>            $concrete = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bind[$abstract];<br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 用于代表匿名函数的类  判断是不是闭包</span><br/>            <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> ($concrete <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">instanceof</span> Closure) {<br/>                $object = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->invokeFunction($concrete, $vars);<br/>            } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">else</span> {<br/>                <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// $this->name[&#39;app&#39;] = think\App</span><br/>                <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->name[$abstract] = $concrete;<br/>                <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 在执行一次本类的make方法,也就是本方法</span><br/>                <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// think\App</span><br/>                <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->make($concrete, $vars, $newInstance);<br/>            }<br/>        } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">else</span> {<br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// think\App</span><br/>            $object = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->invokeClass($abstract, $vars);<br/>        }<br/><br/>        <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> (!$newInstance) {<br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 把创建的容器存起来</span><br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">//$this->instances[&#39;think\App&#39;] = $object;</span><br/>            <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->instances[$abstract] = $object;<br/>        }<br/><br/>        <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> $object;<br/>    }<br/></code>
<span style="display: block; background: url(https://my-wechat.mdnice.com/point.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #282c34; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #282c34; border-radius: 5px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">public</span> <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">function</span> <span class="hljs-title" style="color: #61aeee; line-height: 26px;">invokeClass</span><span class="hljs-params" style="line-height: 26px;">($class, $vars = [])</span><br/>    </span>{<br/>        <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">try</span> {<br/><br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">/**<br/>             * ReflectionClass Object<br/>                (<br/>                [name] => think\App<br/>                )<br/>             */</span><br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 这里就是之前文章提到的反射</span><br/>            $reflect = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">new</span> ReflectionClass($class);<br/><br/><br/>            <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> ($reflect->hasMethod(<span class="hljs-string" style="color: #98c379; line-height: 26px;">&#39;__make&#39;</span>)) {<br/>                $method = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">new</span> ReflectionMethod($class, <span class="hljs-string" style="color: #98c379; line-height: 26px;">&#39;__make&#39;</span>);<br/><br/>                <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> ($method->isPublic() && $method->isStatic()) {<br/>                    $args = <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bindParams($method, $vars);<br/>                    <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> $method->invokeArgs(<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">null</span>, $args);<br/>                }<br/>            }<br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 通过反射获取think\App的构造函数</span><br/>            $constructor = $reflect->getConstructor();<br/><br/>            $args = $constructor ? <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">$this</span>->bindParams($constructor, $vars) : [];<br/>            <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 从给出的参数创建一个新的类实例</span><br/>            <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> $reflect->newInstanceArgs($args);<br/><br/>        } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">catch</span> (ReflectionException $e) {<br/>            <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">throw</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">new</span> ClassNotFoundException(<span class="hljs-string" style="color: #98c379; line-height: 26px;">&#39;class not exists: &#39;</span> . $class, $class);<br/>        }<br/>    }<br/></code>

실행 흐름도

이제 코드가 정리되었으니 이제 실행 흐름도를 정리하여 좀 더 명확하게 살펴보겠습니다.

배움에 대한 끈기, 블로깅에 대한 끈기, 공유에 대한 끈기는 카카가 경력 이후부터 늘 지켜온 신념입니다. 거대 인터넷에 올라온 카카의 글이 여러분에게 조금이나마 도움이 되기를 바랍니다. 저는 카카입니다 다음에 또 만나요

위 내용은 ThinkPHP 컨테이너는 어떻게 인스턴스를 반환합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.