Symfony 4:DIC构建完成后在自定义工厂中手动延迟加载服务
手动在DIC构建后实现自定义工厂的延迟加载服务
嘿,我之前在项目里也碰到过一模一样的问题——容器初始化完成后,自定义工厂里想延迟加载服务,但常规的lazy: true配置不起作用。给你几个经过验证的可行方案:
方案1:借助服务定位器(或容器)延迟获取依赖
如果你的工厂可以接入依赖注入容器(或者更推荐的,一个限定范围的服务定位器),可以在实际创建Example实例时才去获取依赖,从而实现延迟加载:
use Psr\Container\ContainerInterface; class ExampleFactory { private $serviceLocator; // 优先用ServiceLocator而非全量Container,避免滥用容器带来的耦合 public function __construct(ContainerInterface $serviceLocator) { $this->serviceLocator = $serviceLocator; } public function create(): Example { // 只有当调用create()时才会真正初始化LazyLoadedDependency $dependency = $this->serviceLocator->get(LazyLoadedDependency::class); return new Example($dependency); } }
如果是Symfony这类框架环境,你可以通过配置创建仅包含指定服务的ServiceLocator,进一步缩小工厂对容器的依赖范围。
方案2:手动生成延迟代理类
很多依赖注入容器(比如Symfony、Laravel)底层都用了ProxyManager实现懒加载。你可以直接在工厂里手动创建代理实例,完全不依赖容器的自动配置:
use ProxyManager\Factory\LazyLoadingValueHolderFactory; use YourNamespace\LazyLoadedDependency; class ExampleFactory { private $lazyProxyFactory; private $dependencyResolver; // 注入代理工厂和创建依赖的回调函数,解耦依赖创建逻辑 public function __construct(LazyLoadingValueHolderFactory $lazyProxyFactory, callable $dependencyResolver) { $this->lazyProxyFactory = $lazyProxyFactory; $this->dependencyResolver = $dependencyResolver; } public function create(): Example { // 创建代理对象,只有当调用依赖的方法时才会执行初始化逻辑 $lazyDependency = $this->lazyProxyFactory->createProxy( LazyLoadedDependency::class, function (&$wrappedObject, $proxy, $method, $parameters, &$initializer) { // 初始化后取消回调,确保依赖只实例化一次 $initializer = null; $wrappedObject = ($this->dependencyResolver)(); return true; } ); return new Example($lazyDependency); } }
这种方式更符合依赖注入的单一职责原则——工厂只负责生成延迟代理,依赖的创建逻辑由外部注入的回调提供,完全解耦。
方案3:排查是否误手动实例化依赖
如果你的LazyLoadedDependency已经在配置里设了lazy: true但还是提前实例化,很大可能是你在工厂里手动new了这个依赖,而非通过容器获取。即使容器已经构建完成,只要调用$container->get(LazyLoadedDependency::class),容器依然会返回延迟代理实例,不会直接初始化对象。
额外注意事项
- 如果你用具体类做延迟加载,要确保它的构造方法没有副作用(比如直接连接数据库、调用外部API),否则延迟加载的意义会大打折扣。
- 优先针对接口创建代理,既符合面向接口编程的原则,也让延迟加载的逻辑更灵活。
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

