依赖注入是否会导致延迟加载依赖性?
因为您需要将实例传递给构造函数,所以以后不能生成实例
答案 0 :(得分:3)
依赖注入是否会导致延迟加载依赖性?
不,它不会使延迟加载变得不可能。我甚至会争论相反,我甚至会说动态语言(如PHP和Ruby)比静态类型语言(如Java和C#)更容易。
由于您的组件编程为抽象,因此很容易为同一个合同注入一个实现,该实现包含可以延迟加载的实际实现。包装器就像一个代理,这使得消费者不会忘记任何延迟加载甚至正在进行的事实。这增加了可维护性。
我的PHP非常生疏,所以下一个例子可能不是'编译'(任何PHP开发,请随时更新这个例子),但以下显示了这个想法。
这里我们看到一些实现一些业务逻辑的类(ShipOrderHandler
),它依赖于记录器依赖:
class ShipOrderHandler {
private $logger;
function __construct($logger) {
$this->logger = $logger;
}
function Handle($command) {
$this->logger->Log("shipping order " + $command->OrderId);
}
}
class DatabaseLogger {
function Log($message) {
// log the message
}
}
这是我们为ShipOrderHandler
构建对象图的方法:
$handler = new ShipOrderHandler(new DatabaseLogger());
不要想象我们的DatabaseLogger
实际上很难初始化。利用DI和动态语言的强大功能,我们可以简单地为记录器摘要添加代理实现;我们称之为LazyLogger
。我们的新LazyLogger
可能如下所示:
class LazyLogger {
private $loggerFactory;
private $logger;
function __construct($loggerFactory) {
$this->loggerFactory = $loggerFactory;
}
function Log($message) {
if (!$this->logger) $logger = $loggerFactory();
$this->logger.Log($message);
}
}
我们现在可以将此LazyLogger
应用于我们的Composition Root,以便懒惰地创建DatabaseLogger
,而不对我们的应用程序组件进行任何更改:
$handler = new ShipOrderHandler(
new LazyLogger(function() { return new DatabaseLogger() });
这里我们将DatabaseLogger
的创建包装在一个注入LazyLogger
的匿名函数中。当第一次调用LazyLogger
的{{1}}方法时,将调用工厂方法,创建Log
并且DatabaseLogger
将缓存该实例并将使用它直到它超出范围本身。
正如您所看到的,依赖注入实际上并不限制延迟加载的使用;相反:它允许延迟加载而无需在整个应用程序中进行彻底的更改。
这是DI的力量。
答案 1 :(得分:0)
你会在http://php.budgegeria.de/flzsbalQV2中找到一个使用延迟加载的Symfony DI组件示例。
类Bar依赖于Foo,它被配置为服务。当Foo实例化时,将运行回声。如您所见,当第一次访问Foo依赖项方法时,将创建实例。
您需要ocramius / proxy-manager编写器包。也可以将这种惰性行为实现到其他DI容器中。