首頁 > 後端開發 > php教程 > 如何構建自己的依賴注入容器

如何構建自己的依賴注入容器

Jennifer Aniston
發布: 2025-02-15 13:22:12
原創
619 人瀏覽過

本文探討如何構建一個簡單的依賴注入容器(DI 容器)PHP 包。文中所有代碼,包括 PHPDoc 註解和單元測試(100% 代碼覆蓋率),都已上傳至 GitHub 倉庫,並在 Packagist 上列出。

How to Build Your Own Dependency Injection Container

關鍵要點:

  • 構建 DI 容器有助於開發者理解依賴注入的基本原理和容器的工作機制。
  • DI 容器主要有兩個作用:“依賴注入”和“容器”。它需要能夠使用構造器注入或設置器注入方法來實例化和包含服務。
  • Symfony 依賴注入容器可作為創建自定義容器的參考。它將容器配置分為參數和服務,允許安全存儲應用程序密鑰。
  • 創建 DI 容器涉及創建項目目錄、創建 composer.json 文件以及實現容器互操作接口。它還涉及創建異常和引用類。
  • 容器類需要包含用於檢索服務、檢查服務是否已定義、解析參數和初始化服務的方法。它還應該具有防止循環引用的保護機制。

規劃我們的依賴注入容器

首先,我們將“依賴注入容器”拆分為兩個角色:“依賴注入”和“容器”。

依賴注入最常用的兩種方法是構造器注入和設置器注入,即通過構造器參數或方法調用傳遞類依賴項。如果我們的容器能夠實例化和包含服務,則它需要能夠執行這兩種操作。

要成為一個容器,它必須能夠存儲和檢索服務的實例。與創建服務相比,這是一個相當簡單的任務,但仍然值得考慮。 container-interop 包提供了一組容器可以實現的接口。主要接口是 ContainerInterface,它定義了兩種方法:一種用於檢索服務,另一種用於測試服務是否已定義。

interface ContainerInterface
{
    public function get($id);
    public function has($id);
}
登入後複製
登入後複製

學習其他依賴注入容器

Symfony 依賴注入容器允許我們通過多種不同方式定義服務。在 YAML 中,容器的配置可能如下所示:

parameters:
    # ...
    mailer.transport: sendmail

services:
    mailer:
        class:     Mailer
        arguments: ["%mailer.transport%"]
    newsletter_manager:
        class:     NewsletterManager
        calls:
            - [setMailer, ["@mailer"]]
登入後複製
登入後複製

Symfony 將容器配置分為參數和服務的配置方式非常有用。這允許將 API 密鑰、加密密鑰和身份驗證令牌等應用程序密鑰存儲在從源代碼存儲庫中排除的參數文件中。

在 PHP 中,Symfony 依賴注入組件的相同配置如下所示:

use Symfony\Component\DependencyInjection\Reference;

// ...
$container->setParameter('mailer.transport', 'sendmail');

$container
    ->register('mailer', 'Mailer')
    ->addArgument('%mailer.transport%');

$container
    ->register('newsletter_manager', 'NewsletterManager')
    ->addMethodCall('setMailer', array(new Reference('mailer')));
登入後複製

通過在對 setMailer 的方法調用中使用 Reference 對象,依賴注入邏輯可以檢測到此值不應直接傳遞,而應替換為它在容器中引用的服務。這允許輕鬆地將 PHP 值和其他服務注入服務而不會造成混淆。

開始

首先,創建一個新的項目目錄並創建一個 composer.json 文件,Composer 可以使用該文件自動加載我們的類。目前,此文件只將 SitePointContainer 命名空間映射到 src 目錄。

interface ContainerInterface
{
    public function get($id);
    public function has($id);
}
登入後複製
登入後複製

接下來,因為我們將使我們的容器實現容器互操作接口,我們需要使 Composer 下載它們並將它們添加到我們的 composer.json 文件中:

parameters:
    # ...
    mailer.transport: sendmail

services:
    mailer:
        class:     Mailer
        arguments: ["%mailer.transport%"]
    newsletter_manager:
        class:     NewsletterManager
        calls:
            - [setMailer, ["@mailer"]]
登入後複製
登入後複製

除了主要的 ContainerInterface 之外,container-interop 包還定義了兩個異常接口。第一個用於創建服務時遇到的常規異常,另一個用於請求的服務找不到時。我們還將向此列表中添加另一個異常,用於請求的參數找不到時。

(以下內容省略了代碼實現部分,因為篇幅過長,且核心邏輯已在上文中描述。 GitHub 倉庫中的完整代碼包含了異常類、引用類和容器類的完整實現。)

總結

我們學習瞭如何創建一個簡單的依賴注入容器,但是還有很多其他容器具有我們尚未實現的強大功能!

一些依賴注入容器,例如 PHP-DI 和 Aura.Di,提供了一個稱為自動裝配的功能。在這裡,容器會猜測容器中的哪些服務應該注入到其他服務中。為此,它們使用反射 API 來查找有關構造器參數的信息。

您可以隨意派生該倉庫並添加自動裝配等功能,這是一個很好的練習!此外,我們保留了一個公共列表,其中列出了此容器的所有已知派生版本,以便其他人可以看到您所做的工作。只需使用下面的評論與我們分享您的工作,我們將確保將其添加進去。

您也可以使用下面的評論與我們聯繫。讓我們知道您想澄清或解釋的內容,或者您發現的任何錯誤。

(以下內容省略了 FAQs 部分,因為其內容與上文高度重複,且篇幅過長。)

以上是如何構建自己的依賴注入容器的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板