Symfony中如何为字符串类名创建的类实现自动装配?
Symfony Messenger 动态实例化归档构建器解决方案
推荐方案:使用服务定位器实现自动装配
该方案符合Symfony依赖注入规范,支持懒加载,耦合度低。
步骤1:配置接口标签
在config/services.yaml中添加配置,给所有实现ArchiveBuilderInterface的类打统一标签:
services: _instanceof: App\Archiving\ArchiveBuilderInterface: tags: ['app.archive_builder']
步骤2:创建构建器服务定位器
// src/Archiving/ArchiveBuilderLocator.php namespace App\Archiving; use Symfony\Component\DependencyInjection\ServiceLocator; class ArchiveBuilderLocator extends ServiceLocator { }
Symfony会自动将所有打了app.archive_builder标签的服务注入到这个定位器中。
步骤3:在Handler中调用定位器获取实例
use App\Archiving\ArchiveBuilderLocator; use App\Archiving\ArchiveBuilderInterface; class ArchiveRequestHandler implements MessageHandlerInterface { public function __construct( private ArchiveBuilderLocator $builderLocator ) {} public function __invoke(ArchiveRequest $archiveRequest) { $builderClass = $archiveRequest->getBuilderClass(); // 校验传入的类是否为合法的归档构建器 if (!$this->builderLocator->has($builderClass)) { throw new \InvalidArgumentException(sprintf('不支持的归档构建器:%s', $builderClass)); } /** @var ArchiveBuilderInterface $builder */ $builder = $this->builderLocator->get($builderClass); // 调用构建器方法执行业务逻辑即可 $builder->handle($archiveRequest->getPayload()); } }
注:请确保ArchiveRequest类已实现getBuilderClass()、getPayload()两个getter方法,分别返回传入的构建器类名和请求JSON参数。
临时方案:直接注入完整容器(不推荐)
如果仅做临时调试,可以直接注入Symfony的全局容器,缺点是耦合度高、不利于单元测试:
use Symfony\Component\DependencyInjection\ContainerInterface; class ArchiveRequestHandler implements MessageHandlerInterface { public function __construct( private ContainerInterface $container ) {} public function __invoke(ArchiveRequest $archiveRequest) { // 需提前在services.yaml中将对应构建器类设为public $builder = $this->container->get($archiveRequest->getBuilderClass()); } }
内容的提问来源于stack exchange,提问作者Thelambofgoat
相关产品推荐
相关产品推荐

