摘要:比如下面是的入口文件已去掉注釋首先看,其中是的一個(gè)實(shí)例,而類繼承自,所以實(shí)際上就是一個(gè)。標(biāo)記有些時(shí)候,可能需要解析某個(gè)分類下的所有綁定。解析方法數(shù)組方法解析被標(biāo)記綁定解析事件每當(dāng)服務(wù)容器解析一個(gè)對象時(shí)就會觸發(fā)事件。
什么是Service Container
The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection.
從Laravel官方文檔對于Service Container的解釋可以看出,它的作用就是幫助我們管理和進(jìn)行依賴注入的。
為什么要用Service Container在《嘮嘮依賴注入》中,我們看到使用依賴注入可以極大的降低代碼的耦合度,但是也帶來了一個(gè)缺點(diǎn),就是需要自己管理注入的對象。
如果一個(gè)組件有很多依賴,我們需要?jiǎng)?chuàng)建多個(gè)參數(shù)的setter方法??來傳遞依賴關(guān)系,或者建立一個(gè)多個(gè)參數(shù)的構(gòu)造函數(shù)來傳遞它們,另外在使用組件前還要每次都創(chuàng)建依賴,這讓我們的代碼像這樣不易維護(hù)。
所以為依賴實(shí)例提供一個(gè)容器(Service Container),就是一個(gè)實(shí)用而且優(yōu)雅的方法。
比如下面是laravel的入口文件(已去掉注釋):
// public/index.php make(IlluminateContractsHttpKernel::class); $response = $kernel->handle( $request = IlluminateHttpRequest::capture() ); $response->send(); $kernel->terminate($request, $response);
// bootstrap/app.php singleton( IlluminateContractsHttpKernel::class, AppHttpKernel::class ); $app->singleton( IlluminateContractsConsoleKernel::class, AppConsoleKernel::class ); $app->singleton( IlluminateContractsDebugExceptionHandler::class, AppExceptionsHandler::class ); return $app;
首先看bootstrap/app.php,其中$app是IlluminateFoundationApplication的一個(gè)實(shí)例,而IlluminateFoundationApplication類繼承自Container,所以$app實(shí)際上就是一個(gè)Service Container。
然后下面的三個(gè)singleton方法定義了當(dāng)依賴IlluminateContractsHttpKernel、IlluminateContractsConsoleKernel、IlluminateContractsDebugExceptionHandler這三個(gè)接口時(shí),注入哪個(gè)類的單例。
然后看public/index.php,其中的make方法實(shí)際上就是用Service Container來new一個(gè)IlluminateContractsHttpKernel實(shí)例,跟普通new的區(qū)別就是會把他的依賴自動注入進(jìn)去。
是不是很簡潔?
其實(shí)不單是Laravel,像Yii2、Phalcon等框架都通過實(shí)現(xiàn)容器來管理依賴注入。
如何使用Service Container既然是一個(gè)容器,無非就是兩個(gè)事,往里放東西和往外取東西,對應(yīng)到Service Container就是綁定(Binding)和解析(Resolving)。
獲得容器在Laravel的Service Provider中,可以通過$this->app獲取容器,除此之外,還可以使用app()來獲取容器。
如果在Laravel外使用Service Container,直接new一個(gè)IlluminateContainerContainer就可以獲得容器了。
以下都用$container代表獲取到的容器。
綁定綁定返回接口的實(shí)例
//使用閉包 $container->bind("BarInterface", function(){ return new Bar(); }); //或者使用字符串 $container->bind("FooInterface", "Foo");
綁定單例
singletion 方法綁定一個(gè)只會被解析一次的類或接口至容器中,且后面的調(diào)用都會從容器中返回相同的實(shí)例:
$container->singleton("BarInterface", function(){ return new Bar(); });
綁定實(shí)例
你也可以使用 instance 方法,綁定一個(gè)已經(jīng)存在的對象實(shí)例至容器中。后面的調(diào)用都會從容器中返回指定的實(shí)例:
$bar = new Bar(); $bar->setSomething(new Something); $container->instance("Bar", $bar);
情境綁定
有時(shí)候,你可能有兩個(gè)類使用到相同接口,但你希望每個(gè)類都能注入不同實(shí)現(xiàn)。
$container->when("Man") ->needs("PartnerInterface") ->give("Woman"); $container->when("Woman") ->needs("PartnerInterface") ->give("Man");
標(biāo)記
有些時(shí)候,可能需要解析某個(gè)「分類」下的所有綁定。
$container->bind("Father", function () { // }); $container->bind("Mother", function () { // }); $container->bind("Daughter", function () { // }); $container->bind("Son", function () { // }); $container->tag(["Father", "Mother", "Daughter", "Son"], "familyMembers"); $container->bind("Family", function ($container) { return new Family($container->tagged("familyMembers")); });解析
make方法
$foo = $container->make("Foo");
數(shù)組方法
$bar = $container["Bar"];
解析被標(biāo)記綁定
$familyMembers = $container->tagged("familyMembers"); foreach ($familyMembers as $individual) { $individual->doSomething(); }解析事件
每當(dāng)服務(wù)容器解析一個(gè)對象時(shí)就會觸發(fā)事件。你可以使用 resolving 方法監(jiān)聽這個(gè)事件。
$container->resolving(function ($object, $container) { // 當(dāng)容器解析任何類型的對象時(shí)會被調(diào)用... }); $container->resolving("Foo", function (Foo $foo, $container) { // 當(dāng)容器解析「Foo」類型的對象時(shí)會被調(diào)用... });
博客地址:http://haitian299.github.io/2016/05/17/laravel-service-container/
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/21566.html
摘要:實(shí)際上的綁定主要有三種方式且只是一種的,這些已經(jīng)在學(xué)習(xí)筆記之實(shí)例化源碼解析聊過,其實(shí)現(xiàn)方法并不復(fù)雜。從以上源碼發(fā)現(xiàn)的反射是個(gè)很好用的技術(shù),這里給出個(gè),看下能干些啥打印結(jié)果太長了,就不粘貼了。 說明:本文主要學(xué)習(xí)Laravel中Container的源碼,主要學(xué)習(xí)Container的綁定和解析過程,和解析過程中的依賴解決。分享自己的研究心得,希望對別人有所幫助。實(shí)際上Container的綁...
摘要:說明本文主要學(xué)習(xí)容器的實(shí)例化過程,主要包括等四個(gè)過程。看下的源碼如果是數(shù)組,抽取別名并且注冊到中,上文已經(jīng)討論實(shí)際上就是的。 說明:本文主要學(xué)習(xí)Laravel容器的實(shí)例化過程,主要包括Register Base Bindings, Register Base Service Providers , Register Core Container Aliases and Set the ...
摘要:上文書,創(chuàng)建對象需要先創(chuàng)建對象。創(chuàng)建對象的雜活是嵌入在中的。對象使用來管理依賴關(guān)系非常好,但不是必須的。很容易實(shí)現(xiàn),但手工維護(hù)各種亂七八糟的對象還是很麻煩。所有文章均已收錄至項(xiàng)目。 本文翻譯自 Symfony 作者 Fabien Potencier 的 《Dependency Injection in general and the implementation of a Depend...
摘要:現(xiàn)在我們就可以在構(gòu)造函數(shù)或者任何其他通過服務(wù)容器注入依賴項(xiàng)的地方使用類型提示注入接口創(chuàng)建一個(gè)新的類實(shí)例,此處將注入的實(shí)例。自動解析構(gòu)造函數(shù)所需的依賴的服務(wù)容器實(shí)現(xiàn)了接口。 簡單的服務(wù)容器 一個(gè)簡單的 php 5.3 依賴注入容器。 項(xiàng)目地址:https://github.com/godruoyi/easy-container Why 目前比較流行的 PHP 容器: Pimple La...
摘要:用匿名函數(shù)的好處在于,這個(gè)服務(wù)綁定到容器以后,并不會立即產(chǎn)生服務(wù)最終的對象,只有在這個(gè)服務(wù)解析的時(shí)候,匿名函數(shù)才會執(zhí)行,此時(shí)才會產(chǎn)生這個(gè)服務(wù)對應(yīng)的服務(wù)實(shí)例。 前言 ? 老實(shí)說,第一次老大讓我看laravel框架手冊的那天早上,我是很絕望的,因?yàn)檎娴臎]接觸過,對我這種渣渣來說,laravel的入門門檻確實(shí)有點(diǎn)高了,但還是得硬著頭皮看下去(雖然到現(xiàn)在我還有很多沒看懂,也沒用過)。? 后面慢...
閱讀 2139·2019-08-29 16:53
閱讀 2712·2019-08-29 16:07
閱讀 2057·2019-08-29 13:13
閱讀 3278·2019-08-26 13:57
閱讀 1344·2019-08-26 13:31
閱讀 2447·2019-08-26 13:22
閱讀 1234·2019-08-26 11:43
閱讀 2095·2019-08-23 17:14