支付宝扫一扫付款
微信扫一扫付款
(微信为保护隐私,不显示你的昵称)
本功能从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)”,具有与服务所在类相同的特征。你可以注入这个服务到其他服务中,就像通常所做的那样。实际被注入的对象是代理。
为了检查你的代理是否工作,你可以简单查看已接收对象的接口。
1 | var_dump(class_implements($service)); |
如果该类实现了ProxyManager\Proxy\LazyLoadingInterface
,你的lazy loaded服务工作正常。
如果你不想安装代理管理器桥接和ocramius/proxy-manager,则服务容器就会跳过lazy
旗标,转而直接进行常规的实例化。
只要你以任何方式操作这个对象,代理就会被初始化,同时真正的服务就会被实例化。
在ProxyManager文档中,你可以读到更多的关于代理是如何被实例化、被生成、被初始化的信息。
本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。