发现了LazyServiceLoader的循环依赖关系,例如`UserService`

时间:2017-06-14 11:19:42

标签: zend-framework2 circular-dependency zend-servicemanager

在Zend Framework 2中,

我有一个控制器类UserController

  • UserController取决于UserService
  • UserService取决于UserChangedListener
  • UserChangedListener取决于SomeOtherClass
  • SomeOtherClass取决于UserService

所以我的UserControllerSomeOtherClass取决于UserService

我收到错误:

  

例如,找到了LazyServiceLoader的循环依赖项   UserService

我在SomeOtherClass

中注入UserChangedListener时发生了上述错误(即LazyServiceLoader的循环依赖关系)

我有

  

" zendframework / zend-servicemanager":" ^ 2.7.5 || ^ 3.0.3",

UserControllerFactory.php

class UserControllerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $container = $container->getServiceLocator();

        return new UserController(
            $container->get(UserService::class)
        );
    }

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        return $this($serviceLocator, UserController::class);
    }

}

UserServiceFactory.php

class UserServiceFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $service = new UserService(
            $container->get(UserRepository::class)
        );

        $eventManager = $service->getEventManager();
        $eventManager->attach($container->get(UserChangedListener::class));

        return $service;
    }

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        return $this($serviceLocator, UserService::class);
    }
}

UserChangedListenerFactory.php

class UserChangedListenerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $container = $container->getServiceLocator();

        return new UserChangedListener(
            $container->get(SomeOtherClass::class)
        );
    }

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        return $this($serviceLocator, UserChangedListener::class);
    }
}

SomeOtherClassFactory.php

class SomeOtherClassFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $rootLocator = $serviceLocator->getServiceLocator();

        return new SomeOtherClass(
            $rootLocator->get(UserService::class)
        );
    }
}

2 个答案:

答案 0 :(得分:0)

看起来您与UserService具有合法的循环依赖关系。该错误消息告诉您,如果没有UserService,则无法创建UserService

这是通过__construct方法使用依赖注入的良好实践所引入的问题。通过这样做,ZF2将急切将一个非常大的对象图加载到内存中,当你有许多具有复杂嵌套关系的相关“服务”时,你必然会有循环依赖。

ZF2确实提供Lazy Services作为延迟某些对象实例化的解决方案,作为开发人员,您需要决定哪些对象(我建议UserChangedListener)。

或者,为了更新您的代码,您可以将侦听器代码的注册移到UserServiceFactory 之外并转移到Module::onBootstrap()方法。

namespace User;

class Module
{   
    public function onBootstrap(EventInterface $event)
    {
        $serviceManager = $event->getApplication()->getServiceManager();

        // Create the user service first
        $userService = $serviceManager->get(UserService::class);

        $listener = $serviceManager->get(UserChangedListener::class);

        // The create and attach the listener after user service has been created.
        $userService->getEventManager()->attach($listener);
    }

}

如果您使用'聚合'侦听器,则需要这样做。对于简单的事件监听器,您还可以使用SharedEventManager,这可以防止在上面的示例中加载UserService的开销。

答案 1 :(得分:0)

  • UserService依赖于SomeOtherClass通过 UserChangedListener
  • SomeOtherClass取决于UserService

所以基本上对于创建UserService,您首先需要创建SomeOtherClass实例,但是要创建它,您需要创建UserService实例。

我不确定您的架构,但根据类名,您在UserChangedListener附加UserService时看起来有点不对劲。 可能UserService应仅触发事件,并且不应该知道有关此事件的侦听器的任何信息。但同样 - 这只是想法,并且为了得到好的答案,你需要更多地解释这种依赖性。