You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ZF2中ServiceManagerConfig类的configureServiceManager方法作用解析

ZF2中ServiceManagerConfig::configureServiceManager的作用与设计逻辑

问题背景

我在阅读ZF2源码时遇到了ServiceManagerConfig类,对其中的configureServiceManager方法的作用存在疑惑。之前了解到这个方法负责配置ServiceManager实例,完成服务、别名、工厂、初始化器等的注册,但我搞不懂:ServiceManager本身就是用来管理服务的,为什么还要通过这个方法来配置它的服务注册相关内容?

ServiceManagerConfig类代码

class ServiceManagerConfig implements ConfigInterface
{
    /* Services that can be instantiated without factories * @var array*/
    protected $invokables = array('SharedEventManager' => 'Zend\\EventManager\\SharedEventManager', );  
    protected $factories = array(                     /* Service factories  *@var array */
        'EventManager'  => 'Zend\\Mvc\\Service\\EventManagerFactory',
        'ModuleManager' => 'Zend\\Mvc\\Service\\ModuleManagerFactory',
    );
    protected $abstractFactories = array();           /*Abstract factories   * @var array*/
    protected $aliases = array(                    /* Aliases  * @var array */
        'Zend\\EventManager\\EventManagerInterface' => 'EventManager', );
    /*Shared services,* Services are shared by default; this is primarily to indicate services that should NOT be shared @var array  */
    protected $shared = array(
        'EventManager' => false,
    );
    /* Constructor
    * Merges internal arrays with those passed via configuration * @param  array $configuration */
    public function __construct(array $configuration = array())
    {
        if (isset($configuration['invokables'])) {
            $this->invokables = array_merge($this->invokables, $configuration['invokables']);
        }
        if (isset($configuration['factories'])) {
            $this->factories = array_merge($this->factories, $configuration['factories']);
        }
        if (isset($configuration['abstract_factories'])) {
            $this->abstractFactories = array_merge($this->abstractFactories, $configuration['abstract_factories']);
        }
        if (isset($configuration['aliases'])) {
            $this->aliases = array_merge($this->aliases, $configuration['aliases']);
        }
        if (isset($configuration['shared'])) {
            $this->shared = array_merge($this->shared, $configuration['shared']);
        }
    }
    /* Configure the provided service manager instance with the configuration in this class.
    * In addition to using each of the internal properties to configure the service manager, also adds an initializer to inject
    *ServiceManagerAware and ServiceLocatorAware classes with the service manager.
    * @param  ServiceManager $serviceManager
    * @return void */
    public function configureServiceManager(ServiceManager $serviceManager)
    {
        foreach ($this->invokables as $name => $class) {
            $serviceManager->setInvokableClass($name, $class);
        }
        foreach ($this->factories as $name => $factoryClass) {
            $serviceManager->setFactory($name, $factoryClass);
        }
        foreach ($this->abstractFactories as $factoryClass) {
            $serviceManager->addAbstractFactory($factoryClass);
        }
        foreach ($this->aliases as $name => $service) {
            $serviceManager->setAlias($name, $service);
        }
        foreach ($this->shared as $name => $value) {
            $serviceManager->setShared($name, $value);
        }
        $serviceManager->addInitializer(function ($instance) use ($serviceManager) {
            if ($instance instanceof EventManagerAwareInterface) {
                if ($instance->getEventManager() instanceof EventManagerInterface) {
                    $instance->getEventManager()->setSharedManager(
                        $serviceManager->get('SharedEventManager')
                    );
                } else {
                    $instance->setEventManager($serviceManager->get('EventManager'));
                }
            }
        });
        $serviceManager->addInitializer(function ($instance) use ($serviceManager) {
            if ($instance instanceof ServiceManagerAwareInterface) {
                $instance->setServiceManager($serviceManager);
            }
        });

        $serviceManager->addInitializer(function ($instance) use ($serviceManager) {
            if ($instance instanceof ServiceLocatorAwareInterface) {
                $instance->setServiceLocator($serviceManager);
            }
        });
        $serviceManager->setService('ServiceManager', $serviceManager);
        $serviceManager->setAlias('Zend\ServiceManager\ServiceLocatorInterface', 'ServiceManager');
        $serviceManager->setAlias('Zend\ServiceManager\ServiceManager', 'ServiceManager');
    }
}

ServiceManager类中的调用代码

<?php
namespace Zend\ServiceManager;
use ReflectionClass;

class ServiceManager implements ServiceLocatorInterface
{
    /**@#+ Constants */
    const SCOPE_PARENT = 'parent';
    const SCOPE_CHILD = 'child';
    protected $canonicalNames = array();        /*Lookup for canonicalized names. * @var array*/
    protected $allowOverride = false;           /** @var bool*/    
    protected $invokableClasses = array();       /* @var array*/    
    protected $factories = array();             /* @var string|callable|\Closure|FactoryInterface[] */    
    protected $abstractFactories = array();      /* @var AbstractFactoryInterface[]  */    
    protected $delegators = array();           /* @var array[] */    
    protected $pendingAbstractFactoryRequests = array();   /* @var array */    
    protected $lastAbstractFactoryUsed = null;            /* @var string*/    
    protected $lastCanonicalNameUsed   = null;         /*@var string */    
    protected $shared = array();                       /* @var array */   
    protected $instances = array();                     /* Registered services and cached values * @var array*/    
    protected $aliases = array();                      /* @var array*/   
    protected $initializers = array();                   /* @var array*/    
    protected $peeringServiceManagers = array();      /* @var ServiceManager[] */    
    protected $shareByDefault = true;                /*Whether or not to share by default  *@var bool*/    
    protected $retrieveFromPeeringManagerFirst = false;     /** @var bool */    
    protected $throwExceptionInCreate = true;             /* @var bool Track whether not to throw exceptions during create()  */
                                                   /* @var array map of characters to be replaced through strtr */
    protected $canonicalNamesReplacements = array('-' => '', '_' => '', ' ' => '', '\\' => '', '/' => '');
    /*Constructor
     * @param ConfigInterface $config */
    public function __construct(ConfigInterface $config = null)
    {
        if ($config) {
            $config->configureServiceManager($this);
        }
    }
}

核心原因:职责分离与配置解耦

这是典型的职责单一原则和配置与逻辑分离的设计思路:

  1. ServiceManager的核心职责
    ServiceManager本身只专注于服务的运行时管理:比如处理服务的检索、实例化(根据工厂/可调用类规则)、共享实例缓存、别名映射、初始化器执行等。如果把服务注册、配置加载的逻辑也塞进它里面,会导致这个类职责过载,既管"用"又管"建",后续维护和扩展都会变得麻烦。

  2. ServiceManagerConfig的专属角色
    ServiceManagerConfig是专门的配置处理类:

    • 它先把ZF2内置的默认配置和用户自定义的配置合并成统一的结构(比如$invokables、$factories这些数组)
    • 再通过configureServiceManager方法,把这些配置数据转化为ServiceManager内部的状态——也就是调用setInvokableClass、setFactory等方法,把配置规则注入到服务管理器中。
  3. 灵活性与扩展性
    这种设计让配置逻辑可以独立演化:

    • 你可以自定义实现ConfigInterface的配置类,比如从YAML文件、数据库甚至远程接口加载配置,只要实现configureServiceManager方法,就能给ServiceManager配置服务
    • ServiceManager不需要关心配置的来源和加载方式,只需要接收配置好的规则,专注于自己的服务管理本职工作。
  4. 代码细节验证
    看ServiceManager的构造函数,它只接收一个ConfigInterface实例,然后调用其configureServiceManager($this)——这说明ServiceManager把配置的逻辑完全委托给了配置类,自己只提供配置的入口。

而configureServiceManager里的逻辑,就是把ServiceManagerConfig中合并好的配置项,逐个调用ServiceManager的对应方法完成注册,同时还添加了几个通用初始化器(比如给实现ServiceManagerAwareInterface的实例注入服务管理器),这些初始化逻辑也是配置的一部分,统一放在配置类里管理更清晰。

内容的提问来源于stack exchange,提问作者WWW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 07:04:55