6.2. Lazy injection

未匹配的标注

延迟注入

不要将此功能与对象的延迟初始化混淆:PHP-DI总是仅在对象被请求或注入到对象时才创建对象

延迟注入的作用远不止于此:它允许将对象依赖项的创建推迟到实际使用它们的那一刻,而不是之前。

警告:仅应在特殊情况下使用此功能,请阅读本页末尾的何时使用

示例

<?php
class ProductExporter
{
    private $pdfWriter;
    private $csvWriter;

    public function __construct(PdfWriter $pdfWriter, CsvWriter $csvWriter)
    {
        $this->pdfWriter = $pdfWriter;
        $this->csvWriter = $csvWriter;
    }

    public function exportToPdf()
    {
        $this->pdfWriter->write(...);
    }

    public function exportToCsv()
    {
        $this->csvWriter->write(...);
    }
}

$productExporter = $container->get(ProductExporter::class);
$productExporter->exportToCsv();

在这个例子中, exportToPdf() 没有被调用。 PdfWriter已初始化并注入到类中,但从未使用过。

如果PdfWriter的初始化成本很高(例如,如果它有很多依赖性,或者如果它在构造函数中做了很多繁琐的事情),那么延迟注入可以帮你实现:直到它被使用才实例化对象。

如何工作

如果将对象定义为“延迟注入”,PHP-DI将注入:

  • 对象(如果已创建)
  • 或者,如果尚未创建的对象的代理

代理是一种特殊的对象,其外观和行为与原始对象完全相同,因此您无法分辨出两者之间的区别。代理仅在需要时才实例化原始对象。

创建代理很复杂。为此,PHP-DI依赖于ProxyManager,这是一个非常棒的库,由Doctrine,Symfony和Zend开发。

让我们用一个例子来说明。简单起见,我们将不注入延迟对象,但将要求容器返回一个对象:

class Foo
{
    public function doSomething()
    {
    }
}

$container->set('Foo', \DI\create()->lazy());

// $proxy 是一个代理对象,它没有初始化
// 轻量化内存
$proxy = $container->get('Foo');

var_dump($proxy instanceof Foo); // true

// 在代理上调用方法将对其进行初始化
$proxy->doSomething();
// 现在已初始化代理,已经创建并调用了Foo的真实实例

如何使用

您可以将一个对象定义为"延迟注入"。如果将其作为依赖项注入,则将代理替代注入。

安装

延迟注入依赖Ocramius/ProxyManager 库。 默认情况下,PHP-DI未安装该库,您需要安装它:

composer require ocramius/proxy-manager

配置

<?php

return [
    'foo' => DI\create('MyClass')
        ->lazy(),
];

注解

/**
 * @Injectable(lazy=true)
 */
class MyClass
{
}

PHP代码

<?php
$containerPHP->set('foo', \DI\create('MyClass')->lazy());

何时使用

延迟注入需要为声明为lazy的每个对象创建代理对象。不建议在一个应用程序中多次使用此功能。

虽然代理经过了优化,但只有当您定义为延迟注入的对象实例化(例如连接到数据库,写入文件等)时,它们才是有价值的。

性能优化

PHP-DI 需要生为您标记为"lazy "的类生成代理。

默认情况下,这些代理是在每个HTTP请求上生成的,这对开发有利,但对生产不利。

在生产中,应生成代理文件:

// 启用代理并将代理写入到文件并保存在tmp/proxies目录中
$containerBuilder->writeProxiesToFile(true, __DIR__ . '/tmp/proxies');

每次部署时,您都需要清除目录,以避免保留过时的代理。

编译容器时生成代理类

默认情况下,代理是在第一次使用时写入磁盘的。

可以通过启用容器编译预先生成代理类(例如,在部署之前):

// 在容器编译时将代理文件写到var/cache目录中
$containerBuilder->enableCompilation(__DIR__ . '/var/cache');
$containerBuilder->writeProxiesToFile(true, __DIR__ . '/var/cache');

为了使用此功能,必须同时设置两个配置选项。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/php-di/6.0/lazy...

译文地址:https://learnku.com/docs/php-di/6.0/lazy...

上一篇 下一篇
贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~