本篇文章給你們帶來的內容是關於Laravel服務容器的綁定與解析,有必定的參考價值,有須要的朋友能夠參考一下,但願對你有所幫助。php
前言laravel
老實說,第一次老大讓我看laravel框架手冊的那天早上,我是很絕望的,由於真的沒接觸過,對我這種渣渣來講,laravel的入門門檻確實有點高了,但仍是得硬着頭皮看下去(雖然到如今我還有不少沒看懂,也沒用過)。
後面慢慢根據公司項目的代碼對laravel也慢慢熟悉起來了,但仍是停留在一些表面的功能,例如依賴注入,ORM操做,用戶認證這些和我項目業務邏輯相關的操做,而後對於一些架構基礎的,例如服務提供器,服務容器,中間件,Redis等這些一開始就要設置好的東西,我卻是沒實際操做過(由於老大一開始就作好了),因此看手冊仍是有點懵。
因此有空的時候逛逛論壇,搜下Google就發現許多關於laravel核心架構的介紹,以及如何使用的網站(確實看完後再去看手冊就好理解多了),下面就根據一個我以爲不錯的網站上面的教學來記錄一下laravel核心架構的學習
網站地址:https://laraweb.net/ 這是一個日本的網站,我以爲挺適合新手的,內容用瀏覽器翻譯過來就ok了,畢竟日文直翻過來很好理解的web
關於服務容器數據庫
手冊上是這樣介紹的:Laravel 服務容器是用於管理類的依賴和執行依賴注入的工具。依賴注入這個花俏名詞實質上是指:類的依賴項經過構造函數,或者某些狀況下經過「setter」方法「注入」到類中。。。。。。(真的看不懂啥意思)
服務容器是用於管理類(服務)的實例化的機制。直接看看服務容器怎麼用bootstrap
1.在服務容器中註冊類(bind)數組
1瀏覽器 2緩存 |
|
2.從服務容器生成類(make)
1 2 3 |
|
這是服務容器最簡單的使用,下面是對服務容器的詳細介紹
laravel容器基本認識
一開始,index.php 文件加載 Composer 生成定義的自動加載器,而後從 bootstrap/app.php 腳本中檢索 Laravel 應用程序的實例。Laravel 自己採起的第一個動做是建立一個 application/ service container 的實例。
1 2 3 |
|
這個文件在每一次請求到達laravel框架都會執行,所建立的$app便是laravel框架的應用程序實例,它在整個請求生命週期都是惟一的。laravel提供了不少服務,包括認證,數據庫,緩存,消息隊列等等,$app做爲一個容器管理工具,負責幾乎全部服務組件的實例化以及實例的生命週期管理。當須要一個服務類來完成某個功能的時候,僅須要經過容器解析出該類型的一個實例便可。從最終的使用方式來看,laravel容器對服務實例的管理主要包括如下幾個方面:
服務的綁定與解析
服務提供者的管理
別名的做用
依賴注入
先了解如何在代碼中獲取到容器實例,再學習上面四個關鍵
第一種是
1 2 3 4 |
|
第二種是
1 2 3 4 5 6 7 |
|
第三種是
在服務提供者裏面直接使用$this->app。服務提供者後面還會介紹,如今只是引入。由於服務提供者類都是由laravel容器實例化的,這些類都繼承自Illuminate\Support\ServiceProvider,它定義了一個實例屬性$app:
1 2 3 |
|
laravel在實例化服務提供者的時候,會把laravel容器實例注入到這個$app上面。因此咱們在服務提供者裏面,始終能經過$this->$app訪問到laravel容器實例,而不須要再使用app()函數或者App Facade了。
淺義層面理解,容器既然用來存儲對象,那麼就要有一個對象存入跟對象取出的過程。這個對象存入跟對象取出的過程在laravel裏面稱爲服務的綁定與解析。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
還有一個單例綁定singleton,是bind的一種特殊狀況(第三個參數爲true),綁定到容器的對象只會被解析一次,以後的調用都返回相同的實例
1 2 3 4 |
|
在綁定的時候,咱們能夠直接綁定已經初始化好的數據(基本類型、數組、對象實例),還能夠用匿名函數來綁定。用匿名函數的好處在於,這個服務綁定到容器之後,並不會當即產生服務最終的對象,只有在這個服務解析的時候,匿名函數纔會執行,此時纔會產生這個服務對應的服務實例。
實際上,當咱們使用singleton,bind方法以及數組形式,(這三個方法是後面要介紹的綁定的方法),進行服務綁定的時候,若是綁定的服務形式,不是一個匿名函數,也會在laravel內部用一個匿名函數包裝起來,這樣的話, 不輪綁定什麼內容,都能作到前面介紹的懶初始化的功能,這對於容器的性能是有好處的。這個能夠從bind的源碼中看到一些細節:
1 2 3 |
|
看看bind的底層代碼
1 |
|
第一個參數服務綁定名稱,第二個參數服務綁定的結果(也就是閉包,獲得實例),第三個參數就表示這個服務是否在屢次解析的時候,始終返回第一次解析出的實例(也就是單例綁定singleton)。
服務綁定還能夠經過數組的方式:
1 2 3 |
|
綁定大概就這些,接下來看解析,也就是取出來用
1 |
|
這個方法接收兩個參數,第一個是服務的綁定名稱和服務綁定名稱的別名,若是是別名,那麼就會根據服務綁定名稱的別名配置,找到最終的服務綁定名稱,而後進行解析;第二個參數是一個數組,最終會傳遞給服務綁定產生的閉包。
看源碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
|
第一步:
1 2 3 |
|
該方法主要是區分,解析的對象是否有參數,若是有參數,還須要對參數作進一步的分析,由於傳入的參數,也多是依賴注入的,因此還須要對傳入的參數進行解析;這個後面再分析。
第二步:
1 2 3 |
|
若是是綁定的單例,而且不須要上面的參數依賴。咱們就能夠直接返回 $this->instances[$abstract]。
第三步:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
這一步主要是先從綁定的上下文找,是否是能夠找到綁定類;若是沒有,則再從 $bindings[] 中找關聯的實現類;最後尚未找到的話,就直接返回 $abstract 自己。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
若是以前找到的 $concrete 返回的是 $abstract 值,或者 $concrete 是個閉包,則執行 $this->build($concrete),不然,表示存在嵌套依賴的狀況,則採用遞歸的方法執行 $this->make($concrete),直到全部的都解析完爲止。
$this->build($concrete)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
|