摘要:控制反轉容器控制反轉使依賴注入變得更加便捷。有瑕疵控制反轉容器是實現的控制翻轉容器的一種替代方案。容器的獨立使用即使沒有使用框架,我們仍然可以在項目中使用安裝組件來使用的控制反轉容器。在沒有給定任何信息的情況下,容器是無法實例化相關依賴的。
聲明:本文并非博主原創,而是來自對《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當然也不是原汁原味的翻譯,能保證90%的原汁性,另外因為是理解翻譯,肯定會有錯誤的地方,歡迎指正。
歡迎轉載,轉載請注明出處,謝謝!
控制反轉容器 基礎綁定上一張,我們學習了依賴注入,接下來,我們繼續探索的是“控制反轉”或者叫“依賴倒置”。后面我們使用IoC容器來代指如上的定義。IoC容器使類的依賴管理變的非常方便,Laravel的核心就是由這種強大的容器思想來驅動的。IoC容器是Laravel框架重要的組成部分,他將框架中所有組件組織在一起工作。事實上Laravel的Application類就是集成自Container容器類。
控制反轉容器(IoC Container)
控制反轉使依賴注入變得更加便捷。如果在容器中定義好了相關的類或者接口(約定),我們如何在程序中解析、并注入這些對象呢?
Laravel應用中,IoC容器可以使用依照門面設計模式實現的App類來訪問容器。容器中包含了各式各樣的方法,這里我們只介紹一些比較基礎的方法。讓我們以上一章中的BillerInterface和BillingNotifierInterface為基礎,來繼續探討使用Stripe1實現的支付功能。我們可以將Stripe的接口實現按照如下代碼綁定到容器中:
App::bind("BillerInterface", function() { return new StripeBiller(App::make("BillingNotifierInterface")); })
注意這里,我們在綁定了BillerInterface的同時,也注入了BillingNotifierInterface接口實現的具體類,所以要將接口綁定到容器中:
App::bind("BillingNotifierInterface", function() { return new EmailBillingNotifier; });
如上,我們可以理解,容器就是各種接口對應實現類的綁定的地方。一旦他們綁定到容器中,我們就能在整個應用中的任意地方解析并使用他。我們甚至可以在解析器中繼續將其他內容綁定到容器。
有瑕疵?
Laravel控制反轉容器是Fabien Potencier實現的Pimple2控制翻轉容器的一種替代方案。如果你已經在項目中使用到Pimple,盡可安心的升級為Illuminate Container3組件,他為您提供了更多好用的特性!
一旦使用了容器,切換接口實現就是一件非常簡單的事情,簡單到一行代碼就能搞定:
class UserController extends BaseController{ public function __construct(BillerInterface $biller) { $this->biller = $biller; } }
控制器通過容器實例化后,包含EmailBillingNotifier的StripeBiller類就會隨著容器注入到控制器中。現在,若想更換通知器的實現方式,只需要接口綁定的實現即可:
App::bind("BillingNotifierInterface", function() { return new SmsBillingNotifier; });
現在,無需擔心項目中到底哪里用到了這個通知器,只需實現新的SmsBillingNotifier類即可。利用這種方式,我們的應用可以在不同的場景下實現快速切換。
是不是感覺這種切換實現的方式很高大上。想象一下,如果想將短信通知器的服務提供商更換為Twilio。我們只須開發一個使用Twilio通知的實現類,并替換掉綁定到容器中的接口對應的實現類就好。如果在向Twilio的過度中出現了問題,我們還能快速的將容器中接口綁定的類替換回原來的服務,這里只需要那么一丁點改變就能快速實現需求變更。可以看到,依賴注入的優點是超乎想象的。再多幾個例子?
好吧!接著往下看。 有時候,我們想在整個應用中對一個類只進行一次解析,一次實例化。使用容器中的singleton方法即可:
App::singleton("BillingNotifierInterface", function() { return new SmsBillingNotifier; });
現在,容器一蛋解析了訂單通知類,在接下來的整個請求中都會使用同一個已實例化的實例。
容器中的intance方法和singleton有點類似;區別在于你可以傳入一個已存在的對象來更新接口綁定的實例,在后續的使用中,容器都將使用到這個新的對象。
$notifier = new SmsBillingNotifier; App::instance("BillingNotifierInterface", $notifier);
現在我們已經熟悉使用容器進行閉包回調的基礎方法,接下來,讓我們深入挖掘下他更強大的功能:反射。
反射容器的獨立使用
即使沒有使用Laravel框架,我們仍然可以在項目中使用Composer安裝illuminate/container組件來使用Laravel的控制反轉容器。
Laravel容器的一個強大的特性就是能通過反射自動解析依賴。反射具有檢測類及其方法的能力。比如,PHP中的ReflectionClass類允許你檢測一些方法在給定的類中是否可用。PHP函數method_exists也是反射的一種形式。看看下面的代碼,讓我們來把玩一下:
$reflection = new ReflectionClass("StripeBiller"); var_dump($reflection->getMethods()); var_dump($reflection->getConstants());
通過使用PHP的這種特性,Laravel可以實現一些有趣的功能!例如,如下代碼:
class UserController extends BaseController { public function __construct(StripeBiller $biller) { $this->biller = $biller; } }
如上控制器初始化時需要傳入StripeBiller類型的對象,我們可以通過反射進行類型檢測。當Laravel容器沒有綁定相應的解析器,它就會通過反射嘗試解析該類。流程大致如下:
容器中有無StripeBiller解析器?
沒有解析器?映射類StripeBiller判斷其依賴。
遞歸的解析StripeBiller類的所有依賴。
通過ReflectionClass->newInstanceArgs()實例化一個新的StripeBiller。
可以看到,容器為你做了很多繁重的工作,使你能釋放更多的時間用于編碼各種邏輯的代碼類。這就是Laravel容器特有的強大特性,也是它能夠勝任構建大型應用的必殺器。
現在,我們控制器中的代碼修改成這樣,這會怎樣?
class UserController extends BaseController { public function __construct(BillerInterface $biller) { $this->biller = $biller; } }
假如我們沒有對BillerInterface進行綁定,那么容器如何注入其依賴的類呢?注意,接口只是個約定,他是不能進行實例化的。在沒有給定任何信息的情況下,容器是無法實例化相關依賴的。所以我們需要使用bind方法來為接口指定一個默認的類的實現:
App::bind("BillerInterface","StripBiller");
這里我們把字符串替換成一個閉包傳入容器,他會告訴容器任何情況下總是使用StripeBiller這個實現自BillerInterface接口的類。這里,我們又可以只修改一行代碼,就能進行替換掉容器中的綁定的邏輯了。假如我們想使用余額支付來代替現有的支付,我們只需要完成繼承自BillerInterface接口的實現類BalanceInterfacez,同時修改下容器中的綁定:
App::bind("BillerInterface", "BalancedBiller");
應用就會自動解析并使用這個新的支付方式。
同樣我們也可以使用singleton方法綁定接口,這樣在整個請求周期內容器只會進行一次實例化。
App::singleton("BillerInterface", "StripeBiller");
掌握容器
想要深入理解Laravel容器?那就通讀下代碼吧!容器只有一個類文件IlluminateContainerContainer。當你看完這個文件代碼后,肯定能對容器有更深、更全面的認識。
-
2015-04-02 第二次閱讀修正。
2015-02-14 第一次翻譯發布。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/22562.html
摘要:劃下重點,服務容器是用于管理類的依賴和執行依賴注入的工具。類的實例化及其依賴的注入,完全由服務容器自動的去完成。 本文首發于 深入剖析 Laravel 服務容器,轉載請注明出處。喜歡的朋友不要吝嗇你們的贊同,謝謝。 之前在 深度挖掘 Laravel 生命周期 一文中,我們有去探究 Laravel 究竟是如何接收 HTTP 請求,又是如何生成響應并最終呈現給用戶的工作原理。 本章將帶領大...
摘要:本文一大半內容都是通過舉例來讓讀者去理解什么是控制反轉和依賴注入,通過理解這些概念,來更加深入。這種由外部負責其依賴需求的行為,我們可以稱其為控制反轉。工廠模式,依賴轉移當然,實現控制反轉的方法有幾種。 容器,字面上理解就是裝東西的東西。常見的變量、對象屬性等都可以算是容器。一個容器能夠裝什么,全部取決于你對該容器的定義。當然,有這樣一種容器,它存放的不是文本、數值,而是對象、對象的描...
摘要:引述最近看設計模式以及代碼,對于控制反轉以及依賴注入這些概念非常困惑,于是找了一些資料,以下是對于控制反轉的一下理解。其中最常見的方式叫做依賴注入,簡稱,還有一種方式叫依賴查找。在軟件工程中,依賴注入是種實現控制反轉用于解決依賴性設計模式。 引述 最近看設計模式以及laravel代碼,對于控制反轉以及依賴注入這些概念非常困惑,于是找了一些資料,以下是對于控制反轉的一下理解。 概念 Io...
摘要:工廠模式,依賴轉移當然,實現控制反轉的方法有幾種。其實我們稍微改造一下這個類,你就明白,工廠類的真正意義和價值了。雖然如此,工廠模式依舊十分優秀,并且適用于絕大多數情況。 此篇文章轉載自laravel-china,chongyi的文章https://laravel-china.org/top...原文地址: http://www.insp.top/learn-lar... ,轉載務必保...
摘要:框架中就是使用服務容器來實現控制反轉和依賴注入。容器依賴注入的實現實現原理需要了解的知識點閉包匿名函數匿名函數,也叫閉包函數,允許臨時創建一個沒有指定名稱的函數反射以上版本具有完整的反射,添加了對類接口函數方法和擴展進行反向工程的能力。 前言 通過實現laravel 框架功能,以便深入理解laravel框架的先進思想。 什么是服務容器 服務容器是用來管理類依賴與運行依賴注入的工具。La...
閱讀 2125·2019-08-29 16:53
閱讀 2700·2019-08-29 16:07
閱讀 2043·2019-08-29 13:13
閱讀 3268·2019-08-26 13:57
閱讀 1332·2019-08-26 13:31
閱讀 2434·2019-08-26 13:22
閱讀 1222·2019-08-26 11:43
閱讀 2085·2019-08-23 17:14