Новое в Symfony 2.8: Улучшение Dependency Injection

  • Добавлено определения приоритета декоратора сервисов
  • Добавлено логирование неиспользованных тегов
  • Реализованы восстанавливаемые контейнеры
  • Упрощенная регистрация Compiler Passes

Добавлено определения приоритета декоратора сервисов

Декоратор сервисов является мощным средством, чтобы заменить некоторые сервисы фактически, не удаляя их из контейнера. Таким образом, новый сервис может использовать замененные сервисы.

В Symfony 2.8, когда более чем один сервис декорирует другой, вы можете определить приоритет каждого декоратора, чтобы иметь более точный контроль над ними. Новый параметр называется decoration_priority, его значение по умолчанию равно 0, и тем выше его значение, тем раньше декоратор применяется:

services:
    app.service1:
        class: AppBundle\Service\Service1

    app.service2:
        class: AppBundle\Service\Service2
        arguments: ['@app.service2.inner']
        decorates: app.service1
        public: false

    app.service3:
        class: AppBundle\Service\Service3
        arguments: ['@app.service3.inner']
        decorates: app.service1
        decoration_priority: 1
        public: false

В приведенном выше примере, app.service3 сначала применяется, поскольку он определяет приоритет 1 и приоритет для app.service2 равно 0 (значение по умолчанию). Таким образом, эта конфигурация эквивалентна следующему коду PHP:

$this->services['app.service1'] = new Service2(new Service3(new Service1())));

Добавлено логирование неиспользованных тегов

В Symfony 2.8, когда в конфигурации сервиса добавляется тег, который в дальнейшем не используется в приложении, в лог сбрасывается сообщение, например:

Tag "this_tag_is_not_used" was defined on service "app.service1" but
was never used.

Все теги служб встроенных в Symfony были добавлены в белый список  (например, console.command и twig.extension), чтобы избежать загрязнения лог-файлов бесполезными сообщениями.

Кроме того, если имя неиспользованного тега похоже на любой из других тегов, в лог-сообщение будет добавить раздел «Возможно, вы имели в виду«, потому что это, вероятно, могло быть опечаткой в вашей конфигурации.

Например, при использовании следующей конфигурации:

services:
    app.service1:
        class: AppBundle\Service\Service1
        tags:
            -  { name: 'kenrel.event_listener', ... }

Вы увидите следующее лог-сообщение:

Tag "kenrel.event_listener" was defined on service "app.service1", but
was never used. Did you mean "kernel.event_listener"?

Реализованы восстанавливаемые контейнеры

Symfony 2.8 включает в себя новый Resettable ContainerInterface, который определяет единственный метод, называемый reset(). Этот метод позволяет освободить память, когда контейнер больше не используется.

Класс ядра Symfony  вызывает этот метод во время процесса завершения работы:

// src/Symfony/Component/HttpKernel/Kernel.php
// ...
public function shutdown()
{
    // ...

    if ($this->container instanceof ResettableContainerInterface) {
        $this->container->reset();
    }
}

Сервис контейнеров Symfony реализует этот интерфейс, чтобы удалить ссылки на все сервисы во время завершения работы, улучшая работу сервисов деструкторов и контейнера через refcounting, не дожидаясь сборки мусора в PHP:

// src/Symfony/Component/DependencyInjection/Container.php
// ...
public function reset()
{
    // ...

    $this->services = array();
}

Упрощенная регистрация Compiler Passes

Compiler passes позволяют изменять контейнер в то время, когда сервисы Symfony компилирует его и перед тем, как он начинает использоваться приложением. В Symfony 2.7 и предыдущих версиях, вам необходимо было зарегистрировать эти расширения следующим образом:

namespace AppBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use AppBundle\DependencyInjection\Compiler\CustomPass;

class AppBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $container->addCompilerPass(new CustomPass());
    }
}

В Symfony 2.8, этот код больше не нужен, потому что, ваши расширения реализации CompilerPassInterface они будут автоматически зарегистрированы и метод process() будет выполняться во время компиляции контейнера.

Источник: http://symfony.com/blog/new-in-symfony-2-8-dependencyinjection-improvements

Добавить комментарий

Ваш адрес email не будет опубликован.

двенадцать + пятнадцать =