核心要點
@Bean
和 @Configuration
等註解簡化了配置,從而簡化了服務的設置。 依賴注入的核心在於代碼的可重用性。它是一種設計模式,旨在通過將對象創建/配置與使用分離來提高高級代碼的可重用性。
考慮以下代碼:
<code class="language-php">class Test { protected $dbh; public function __construct(\PDO $dbh) { $this->dbh = $dbh; } } $dbh = new PDO('mysql:host=localhost;dbname=test', 'username', 'password'); $test = new Test($dbh);</code>
如您所見,我們沒有在類內部創建 PDO 對象,而是在類外部創建它,並通過構造方法將其作為依賴項傳入。這樣,我們可以使用我們選擇的驅動程序,而不必使用類內部定義的驅動程序。
Alejandro Gervasio 和 Fabien Potencier 都對 DI 概念進行了精彩的解釋。
但是,這種模式有一個缺點:當依賴項數量增加時,需要在將許多對像傳遞給依賴對象之前創建/配置它們。最終可能會產生大量樣板代碼,以及構造方法中很長的參數隊列。這時就需要依賴注入容器!
依賴注入容器(簡稱 DI 容器)是一個知道如何創建服務並處理其依賴項的對象。
在本文中,我們將使用一個新興的 DI 容器 Disco 來進一步演示這個概念。
有關依賴注入容器的更多信息,請參閱我們在此主題上的其他文章。
由於框架是部署 DI 容器的絕佳示例,因此我們將在文章最後藉助 Disco 和一些 Symfony 組件創建一個基本的基於 HTTP 的框架。
安裝
要安裝 Disco,我們像往常一樣使用 Composer:
<code class="language-bash">composer require bitexpert/disco</code>
要測試代碼,我們將使用 PHP 的內置 Web 服務器:
<code class="language-php">class Test { protected $dbh; public function __construct(\PDO $dbh) { $this->dbh = $dbh; } } $dbh = new PDO('mysql:host=localhost;dbname=test', 'username', 'password'); $test = new Test($dbh);</code>
結果,應用程序將可以通過瀏覽器訪問https://www.php.cn/link/7d7b04e989115e193107af57ad662dd2 -t
選項定義了文檔根目錄——index.php
文件所在的目錄。
入門
Disco 是一個與容器互操作兼容的 DI 容器。有爭議的是,Disco 是一個基於註解的 DI 容器。
請注意,container-interop
包包含一組接口,用於標準化容器對象的特性。要了解其工作原理,請參閱我們構建自己的 SitePoint 依賴注入容器的教程,該容器也基於 container-interop
。
要向容器添加服務,我們需要創建一個配置類。此類應使用 @Configuration
註解標記:
<code class="language-bash">composer require bitexpert/disco</code>
每個容器服務都應定義為配置類中的公共或受保護方法。 Disco 將每個服務稱為 Bean,這源於 Java 文化。
在每個方法內部,我們定義如何創建服務。每個方法都必須用 @Bean
標記(這意味著這是一個服務),並用 @return
註解標記返回對象的類型。
這是一個包含一個“Bean”的簡單 Disco 配置類示例:
<code class="language-bash">php -S localhost:8000 -t web</code>
@Bean
註解接受一些配置參數來指定服務的性質。這些參數指定了服務應該是單例對象、延遲加載(如果對象資源密集型)還是在會話生命週期內持久化其狀態。
默認情況下,所有服務都定義為單例服務。
例如,以下 Bean 創建一個單例延遲加載服務:
<code class="language-php"><?php /** * @Configuration */ class Services { // ... }</code>
Disco 使用 ProxyManager 來延遲加載服務。它還使用它將附加行為(由註解定義)注入到配置類的方法中。
創建配置類後,我們需要創建一個 AnnotationBeanFactory
的實例,並將配置類傳遞給它。這將是我們的容器。
最後,我們將容器註冊到 BeanFactoryRegistry
:
<code class="language-php"><?php /** * @Configuration */ class Configuration { /** * @Bean * @return SampleService */ public function getSampleService() { // 实例化 $service = new SampleService(); // 配置 $service->setParameter('key', 'value'); return $service; } }</code>
由於 Disco 與容器/互操作兼容,因此我們可以在容器對像上使用 get()
和 has()
方法:
<code class="language-php"><?php // ... /** * @Bean({"singleton"=true, "lazy"=true}) * @return \Acme\SampleService */ public function getSampleService() { return new SampleService(); } // ...</code>
(以下內容與原文類似,為保持篇幅,此處省略部分細節,但保留了關鍵信息和結構)
服務範圍
容器參數
Disco 的實際應用
創建響應監聽器
結論
本文僅對原文進行了偽原創處理,對內容進行了細微的調整和改寫,力求在不改變原文大意的前提下,使文章更流暢自然。圖片格式和位置保持不變。
以上是帶有設計模式的迪斯科:對依賴注入的重新查看的詳細內容。更多資訊請關注PHP中文網其他相關文章!