「在之前的文章中我們簡單的梳理了一下容器類,接下來就是對其中一個細節進行深度分析。
」
Container實例呼叫make方法
本文沒有太多文字解析,都在程式碼註解中說明了執行過程。
程式碼static::getInstance()
傳回了Container的實例後,就會去呼叫本類別的make方法,接下來就是對make方法進行詳解了。
在開始閱讀make方法裡邊的原始碼之前,我們需要先對幾個屬性進行簡單的梳理一下。
這四個屬性一定要有點印象,並且一定要區別instance和instances。
這兩個屬性一個是單例模式傳回目前類別的實例,一個是容器中的所有的實例。
第一次執行結果
<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['app'] = 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['think\App']不存在走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['app'] = 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['think\App'] = $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;">'__make'</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;">'__make'</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;">'class not exists: '</span> . $class, $class);<br/> }<br/> }<br/></code>
執行流程圖
既然把程式碼都理清楚了,這時來理一下執行的流程圖可以看的更清楚。
「堅持學習、堅持寫博、堅持分享是咔咔從業以來一直所秉持的信念。希望在偌大互聯網中咔咔的文章能帶給你一絲絲幫助。我是咔咔,下期見。
」
以上是ThinkPHP容器之容器是如何傳回實例的的詳細內容。更多資訊請關注PHP中文網其他相關文章!