Ленивые сервисы¶
See also
Ещё один способом лениво внедрять сервисы - через настройщик сервисов.
Почему ленивые сервисы?¶
В некоторых случаях, вы можете захотеть внедрить сервис, который немного тяжёлый для
инстанциации, но не всегда используется внутри вашего объекта. Например, представьте,
что у вас есть NewsletterManager
и вы внедряете в него сервис mailer
. Только
несколько методов в вашем NewsletterManager
действительно используют mailer
,
но даже когда он вам не нужн, сервис mailer
всегда инстанциируется, чтобы построить
ваш NewsletterManager
.
Решением этого являются ленивые сервисы. С ленивым сервисом на самом деле
внедряется “прокси” сервиса mailer
. Он выглядит и ведёт себя точно так
же, как mailer
, кроме того, что mailer
на самом деле не инстанциируется
до того, как вы начнёте какое-либо взаимодействие с прокси.
Установка¶
Чтобы использовать инстанциацию ленивого сервиса, вам всегда в первую очередь
понадобится установить пакет ocramius/proxy-manager
:
1 | $ composer require ocramius/proxy-manager
|
Note
Если вы не используете комплексный фреймворк, вы также должны установить мост ProxyManager
1 | $ composer require symfony/proxy-manager-bridge
|
Конфигурация¶
Вы можете отметить сервис как lazy
(ленивый), изменив его определение:
- YAML
1 2 3
services: AppBundle\Twig\AppExtension: lazy: true
- XML
1 2 3 4 5 6 7 8 9 10
<?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="AppBundle\Twig\AppExtension" lazy="true" /> </services> </container>
- PHP
1 2 3 4
use AppBundle\Twig\AppExtension; $container->register(AppExtension::class) ->setLazy(true);
Как только вы внедрите сервис в другой сервис, должен внедриться виртуальный
прокси с той же подписью класса, который будет представлять сервис. То же
самое происходит при вызове Container::get()
напрямую.
Сам класс будет инстанциирован как только вы попробуете взаимодействовать с сервисом (например, вызвать один из его методов).
Чтобы проверить, работает ли ваш прокси, вы можете просто проверить интерфейс полученного объекта:
dump(class_implements($service));
// вывод должен включать в себя "ProxyManager\Proxy\LazyLoadingInterface"
Note
Если вы не установите мост ProxyManager и ocramius/proxy-manager,
контейнер будет просто пропускать метку lazy
и инстанциировать сервис,
как обычно.
Дополнительные источники¶
Вы можете прочитать больше о том, как инстанциируются, генерируются и инициализируются прокси в документации ProxyManager.
Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.