五月
23
2016

symfony 的惰性服务(Lazy Services)

为什么需要惰性服务?

在某些时候,你也许需要向系统中注入一个笨重的实例(功能繁多庞大),但是这个实例你又只是偶尔才会在某些地方用到。举个例子,假如你有一个 通信管理器(NewsletterManager) ,你在其中注入了一个 mailer 邮件服务。在这个通信管理器中,只有屈指可数的一两个方法会用到这个 mailer 服务,然而不管你是否需要用到这个 mailer 服务,这个 mailer 服务总会被实例化,用于构建你的通信管理器。

这个时候,为通信管理器配置一个惰性服务,就可以解决这个让人尴尬的问题了。通过惰性服务,系统会将 mailer 服务的一个代理(proxy) 注入到通信管理器中,这个代理将扮演 mailer 服务的角色,但是它不会被实例化。直到通信管理器真正需要用到 mailer 服务的时候,这个代理才会帮助实例化这个 mailer 服务。

安装

为了正常使用惰性服务功能,你需要首先安装 ProxyManager Bridge

$ composer require symfony/proxy-manager-bridge

如果你使用了整个 symfony 框架,那么 ProxyManager Bridge 已经内置于系统中了,你只需要再加入 Proxy Manager,运行如下命令即可:

$ composer require ocramius/proxy-manager:~1.0

然后编译你的容器,确保你已经为惰性服务设置了代理

配置

你可以通过标记服务的 lazy 来控制服务定义。

YAML

services:
     foo:
       class: Acme\Foo
       lazy: true

XML

<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>
        <service id="foo" class="Acme\Foo" lazy="true" />
    </services>
</container>

PHP

use Symfony\Component\DependencyInjection\Definition;

$definition = new Definition('Acme\Foo');
$definition->setLazy(true);
$container->setDefinition('foo', $definition);

接下来,你可以从服务容器(Container)中载入服务:

$service = $container->get('foo');

到这里,$service 变量得到了一个与服务本身结构完全一样的虚拟代理。你也可以像正常情况那样注入你的服务到另外一个服务中。实际上,这个时候依然是把一个服务代理注入到了另外一个服务器中。

想要检查你的服务代理是否有正常工作,你可以很容易地通过检查得到的对象说实现的接口进行验证:

var_dump(class_implements($service));

如果你没有安装 ProxyManager Bridgeocramius/proxy-manager,服务容器会忽略 lazy 属性,然后向正常情况那样实例化对应的服务。

当服务代理初始化完成以后,一旦系统任何地方真正需要用到某个被代理的服务,该服务就会被实例化。

相关资料

如果你想要了解服务代理是如何实例化、生成和初始化的,你可以阅读以下资料:

documentation of ProxyManager.

该篇资料的原文:点击这里

非特殊注明博文为 爱PHP吧(www.iphp8.com)原创内容,转载请注明原文地址:http://www.iphp8.com/?post=88

评论

发表评论:

(选填)

(选填)