入口檔案 index.php
1、載入框架依賴
2、建立 app 容器
3、解析 Http\Kernel.php 核心
4、執行請求操作
5、返回結果
6、終止應用程式
app.php 檔案(require_once DIR.'/../bootstrap/app.php')
1、建立容器
2、繫結 Http\Hernel.php 到容器
3、繫結 Console\Kernel.php 到容器
4、繫結 Exception\Hadnler.php 到容器
5、返回 app 容器
app 容器
列印 app 容器
1、serviceProviders 屬性
用於存放所有已經註冊完畢的服務提供者
2、loadedProviders 屬性
跟 serviceProviders 陣列類似,標記方式不同
3、deferredServices 屬性
用來儲存所有延遲載入服務提供者
4、resolved 屬性
服務解析完畢,都會在 resolved 屬性裡面存入一條記錄,表示繫結已經解析過
5、bindings 屬性
記錄所有繫結
6、instances 屬性
在第一次解析繫結時,如果 shared 為 true則都會往 instances 屬性裡面存入一條記錄
7、aliases 屬性
服務繫結的別名,別名數量無限制
註冊服務提供者
註冊服務提供者只需要繼承 ServiceProvider 抽象類即可(放在那兒都可以),並在 config/app.php providers 陣列
裡面註冊或使用 app()->register(TestProvider::class)(此方法 $defer 屬性無效) 即可
1、繼承 ServiceProvider 抽象類
2、建立 register 方法並使用 app 容器繫結服務(可繫結任意數量服務)
3、建立 boot 方法,初始化所繫結的服務
4、$defer 屬性為是否延遲載入,為 true 會存入到 deferredServices 屬性,程式註冊時會呼叫 ServicePr
ovider 抽象類的 isDeferred() 方法 『必須在config/app.php providers中註冊』
5、事件觸發註冊服務提供者,ServiceProvider 抽象類的 when 方法返回一個陣列,陣列裡麵包含事件
名稱 如:[TestEvent::class],『$defer 必須為 true』
注意:
PHP 在處理請求前,都會從入口檔案把所有 PHP 檔案都掃描一遍。Laravel 為了效能考慮,會在第一
次初始化的時候,把所有服務提供者都快取到 bootstrap/cache/service.php 檔案裡面,所以有時候在
改或增了服務提供者,重新整理可能不生效,這有可能是快取所致,這時把 service.php 與 packages.php
刪除再重試
註冊服務提供者別名
app()->alias('testProvider','test') 別名數量無限制
app 容器繫結
1、app()->bind($abstract, $concrete = null, $shared = false)
第一個引數是服務繫結名稱,第二個引數是繫結結果(引數型別:\Closure|string|null),第三個引數是否共享(類似
單例),預設為 false,第二個引數,如果是非閉包,內部會包裹上閉包,好處是延遲載入,節約空間
2、app()->singleton($abstract, $concrete = null)
第一個引數是服務繫結名稱,第一個引數是繫結結果,在內部是呼叫了 app()->bind($abstract, $concrete = null, true),
第三個引數為 true
3、app()['test'] = function(){ return 'test' }
使用了 PHP ArrayAccess 介面,在內容呼叫了 app()->bind() 方法,第三個引數為 false
4、app()->instance('test',例項)
繫結一個例項,跟上面三個比,就是少了一個閉包
app 容器解析
1、app($abstract, $parameters = [])
第一個引數是服務繫結的名稱或別名,第二個引數為上下文名稱或別名
2、app()->make($abstract, $parameters = [])
同上
3、app()[$abstract]
只有第一個引數,使用了 PHP ArrayAccess 介面
DI 依賴注入
DI 是 IOC 的一種實現,DI 是一種設計模式,IOC 是一種設計思想,DI 實現原理是使用 PHP 反射機制來反射出相應依賴對
象名稱,通過 aliases 屬性得到服務名稱,然後從容器解析出服務例項,最後傳入對應方法,這個過程就是所謂的依賴注入
總結
Laravel 是一個元件式框架,實現了高度解耦,再使用 IOC 容器來管理解耦後的元件,我把這個容器理解為使用了物件的高階註冊樹,當元件越來越多時,那麼這個容器物件不是越來越大嗎?所以 Laravel 使用了閉包來延遲載入,但是有個問題,如果每次獲取都去 new 一次,不是很浪費時間與空間嗎?在能滿足需求的情況下,能不能只 new 一次(類似單例),所以 Laravel 又引入了 shared 來實現單例,用 instances 屬性來儲存單例(服務在生命週期內,shared 不可更改,而且 Laravel 大部分服務 shared 都為 true),現在又有個需求,當某個動作發生時,就觸發服務載入?所以 Laravel 又加入了 when 方法來繫結事件,前提是這個服務 shared 必須為 true。