Lazy服务

3.4 版本
维护中的版本

为何会有Lazy服务 

本功能从Symfony2.3开始引入。

某些情况下,你需要注入一些“实例化时负载较重”的服务,但在你的对象中它并不是总被用到。例如,假设你有一个NewsletterManager,并向其注入一个Mailer服务。只有NewsletterManager中的少数方法用到了mailer,但是当你并不需要时,该mailer服务始终会被实例化,因为在构造NewsletterManager时需要用到它。

配置懒服务(lazy services)是解决办法之一。通过lazy服务,一个mailer服务的“代理(proxy)”被实际注入,它看上去和运行时都很像mailer,除了mailer未被真正实例化,直到你和代理进行了某种方式的互动。

安装 

为了使用lazy服务,你需要安装ProxyManage bridge

1
$  composer require symfony/proxy-manager-bridge

如果你使用完整版框架,“代理管理器桥”(proxy manager bridge)已经内置,但要实际发生作用的话还需包容一下。所以请运行:

1
$  php composer.phar require ocramius/proxy-manager:~1.0

然后请重新编译你的服务容器,来确保你可以得到lazy service的一个代理。

配置 

你可以将服务标记为lazy,通过如下定义:

1
2
3
4
services:
   foo:
     class: Acme\Foo
     lazy: true
1
2
3
4
5
6
7
8
9
<?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>
1
2
3
4
5
use Symfony\Component\DependencyInjection\Definition;
 
$definition = new Definition('Acme\Foo');
$definition->setLazy(true);
$container->setDefinition('foo', $definition);

然后你可以从容器中取用服务:

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

此时,取出的服务应该是一个“虚拟代理(virtual proxy)”,具有与服务所在类相同的特征。你可以注入这个服务到其他服务中,就像通常所做的那样。实际被注入的对象是代理。

为了检查你的代理是否工作,你可以简单查看已接收对象的接口。

如果该类实现了ProxyManager\Proxy\LazyLoadingInterface,你的lazy loaded服务工作正常。

如果你不想安装代理管理器桥接ocramius/proxy-manager,则服务容器就会跳过lazy旗标,转而直接进行常规的实例化。

只要你以任何方式操作这个对象,代理就会被初始化,同时真正的服务就会被实例化。

附加资源 

ProxyManager文档中,你可以读到更多的关于代理是如何被实例化、被生成、被初始化的信息。

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)