在没有serviceLocator-> get()方式的ZF2中依赖注入的新方式是否效率更低?

Moo*_*zer 4 php dependency-injection overhead zend-framework2 zend-framework3

由于zend-mvc的2.7.0版本已ServiceLocatorAwareInterface被删除,因此$this->serviceLocator->get()控制器内部的调用也是如此.

这就是为什么几天前我对我的所有模块进行了大量重构,通过构造函数注入所需的服务/对象,使用工厂来处理大部分内容.

当然,我理解为什么这是更好/更清洁的做事方式,因为现在更容易看到家属.但另一方面:

这会导致繁重的开销和更多从未使用过的类实例,不是吗?

我们来看一个例子:

因为我的所有控制器都有依赖关系,所以我为所有控制器创建了工厂.

CustomerControllerFactory.php

namespace Admin\Factory\Controller;
class CustomerControllerFactory implements FactoryInterface {
    public function createService(ServiceLocatorInterface $controllerManager) {
        $serviceLocator = $controllerManager->getServiceLocator();
        $customerService = $serviceLocator->get('Admin\Service\CustomerService');
        $restSyncService = $serviceLocator->get('Admin\Service\SyncRestClientService');

        return new \Admin\Controller\CustomerController($customerService, $restSyncService);
    }
}
Run Code Online (Sandbox Code Playgroud)

CustomerController.php

namespace Admin\Controller;

class CustomerController extends AbstractRestfulController {
    public function __construct($customerService, $restSyncService) {
        $this->customerService = $customerService;
        $this->restSyncService = $restSyncService;
    }
}
Run Code Online (Sandbox Code Playgroud)

module.config.php

'controllers' => [
  'factories' => [
    'Admin\Controller\CustomerController' => 'Admin\Factory\Controller\CustomerControllerFactory',
  ]
],
'service_manager' => [
  'factories' => [
    'Admin\Service\SyncRestClientService' => 'Admin\Factory\SyncRestClientServiceFactory',
  ]
]
Run Code Online (Sandbox Code Playgroud)

SyncRestClientServiceFactory.php

namespace Admin\Factory;
class SyncRestClientServiceFactory implements FactoryInterface {
    public function createService(ServiceLocatorInterface $serviceLocator) {
        $entityManager = $serviceLocator->get('doctrine.entitymanager.orm_default');
        $x1 = $serviceLocator->get(...);
        $x2 = $serviceLocator->get(...);
        $x3 = $serviceLocator->get(...);
        // ...

        return new \Admin\Service\SyncRestClientService($entityManager, $x1, $x2, $x3, ...);
    }
}
Run Code Online (Sandbox Code Playgroud)

SyncRestService是一个复杂的服务类,它查询我们系统的某些内部服务器.它有很多依赖项,并且总是在请求来到CustomerController时创建.但这种同步服务用于内部syncAction()的CustomerController的!我用简单的前$this->serviceLocator->get('Admin\Service\SyncRestClientService')内侧syncAction()所以才把它被实例化.

通常,看起来很多实例是在每个请求中通过工厂创建的,但是大多数依赖项都没有使用.这是一个问题,因为我的设计还是"通过构造函数进行依赖注入"的正常副作用行为?

mar*_*osh 8

在我看来,这是依赖注入通过构造函数的正常效果.

我认为您现在有两个选项(不是互斥的)来改善您的应用程序的工作方式:

  1. 拆分控制器,以便仅在需要时才会实现依赖关系.这肯定会产生更多的课程,更多的工厂等等,但是你的代码将获得更多的单一责任原则

  2. 您可以使用Lazy Services,这样,即使某些服务是整个控制器的依赖项,它们实际上只会在第一次被调用时进行实例化(因此,对于未调用它们的操作永远不会!)