Zend \ Di \ Di定义和记忆

时间:2013-03-01 08:31:51

标签: php dependency-injection zend-framework2 memo

在我的ZF2应用程序中,我使用Zend\Di\Di来创建我的所有类实例。使用Zend\Di\Definition\CompilerDefinition扫描DI定义并使用APC进行缓存。这避免了在运行时使用慢速反射扫描类。如果在实例创建期间存在异常(由于过时的DI定义),则重新扫描代码,缓存定义,并再次创建实例。

这在开发过程中非常方便,因为不必为新类或更改的构造函数编写或更改工厂方法/闭包。我的构造函数遵循一定的约定(只有类型提示的参数和单个$ params数组)以确保依赖注入工作而不指定其他构造函数参数。

到目前为止,这表现良好,避免了错误(没有过时的工厂方法),并加快了开发速度。但是,扫描的定义目前在APC中是1.8MB(序列化阵列),而且还在增长。由于必须在每次请求时从缓存加载它们,我担心如果在短时间内有太多请求,内存将耗尽。我没有负载测试设置来模拟这个。

我知道推荐的方法是使用Zend \ ServiceManager并为每个类编写工厂闭包,而不是使用Zend \ Di \ Di.但我认为这是一项很多工作,在开发过程中非常讨厌。

在这种情况下,您是否建议重构Zend \ ServiceManager?

2 个答案:

答案 0 :(得分:2)

我编写了一个ZF2模块来帮助您解决此问题:https://github.com/aimfeld/ZendDiCompiler

ZendDiCompiler 是一个Zend Framework 2模块,它使用自动生成的工厂代码进行依赖注入。它为您节省了大量的工作,因为不再需要编写Zend \ ServiceManager工厂关闭并手动保持它们是最新的。

ZendDiCompiler 扫描您的代码(使用Zend \ Di)并自动创建工厂方法。如果工厂方法已过时,ZendDiCompiler会在后台更新它们。因此,您可以更快地开发,避免因过时的工厂方法而导致的错误,并在生产中体验出色的性能!

答案 1 :(得分:1)

这正是我在博文中关于Zend\Di and RAD所揭示的内容。

虽然Zend\Di有利于开发,但它在生产中是一个巨大的内存和性能瓶颈。即使您缓存定义,它仍然使用ReflectionClasscall_user_func_array()来操作您的实例。它还必须执行许多对齐注入参数所需的周围操作:只需通过Zend\Di查看对象实例化期间对array_merge的调用次数。

我编写了一个模块来处理Zend\Di\Di实例管理器到闭包的编译:OcraDiCompiler。它需要一些清理,但它的工作是通过跟踪Zend\Di内部的实例化逻辑来生成代码工厂/闭包。如果你想“复活”它,我很乐意帮忙,因为它在我的TODO列表中,但现在优先级较低。

无论如何,通过ServiceManager将实例化逻辑移动到工厂/闭包并不像你期望的那么多,所以不要害怕并尝试一下:你可能会喜欢它。