简体   繁体   中英

Circular dependency for LazyServiceLoader was found for instance `UserService`

In Zend Framework 2,

I have a controller class UserController

  • UserController is dependent on UserService
  • UserService is dependent on UserChangedListener
  • UserChangedListener is dependent on SomeOtherClass
  • SomeOtherClass is dependent on UserService

So here my UserController and SomeOtherClass are dependent on UserService .

I am getting error :

Circular dependency for LazyServiceLoader was found for instance UserService

The above error (ie Circular dependency for LazyServiceLoader) occurred when I injected SomeOtherClass in UserChangedListener

And I have

"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)
        );
    }
}

Looks like you have a legitimate circular dependency with UserService . The error message is telling you that the UserService cannot be created without the UserService .

This is really a problem introduced by the good practice of using dependency injection via the __construct method. By doing so, ZF2 will eager load a very large object graph into memory, when you have lots of related 'services' that have complex nested relationships you are bound to have circular dependencies.

ZF2 does offer Lazy Services as a solution to delay the instantiation of certain objects that as the developer you will need to decide on which ones (I would suggest UserChangedListener ).

Alternatively to update your code, you could move the registration of the listener code outside of the UserServiceFactory and into the Module::onBootstrap() method.

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);
    }

}

This would be required if you are using the 'aggregate' listeners. For simple event listeners you can also use the SharedEventManager which would prevent the overhead of loading the UserService in the above example.

  • UserService is dependent on SomeOtherClass through UserChangedListener
  • SomeOtherClass is dependent on UserService

So basically for creation UserService you need first create SomeOtherClass instance, but for create it you need UserService instance to be created already.

I'm not sure about your architecture, but according to class names it looks bit wrong that you attach UserChangedListener in UserService . Probably UserService should only fire events, and shouldn't know anything about listeners for this events. But again - that just idea, and for good answer you need to explain this dependencies bit more.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM