依赖注入
Magento 2使用依赖性注入来取代Magento 1.x中Mage类所提供的功能。
依赖注入是一种设计模式,它允许一个对象A向提供这些依赖关系的外部对象B声明其依赖关系。A声明的依赖关系通常是类的接口,B提供的依赖关系是这些接口的具体实现。
这允许代码的松散耦合,因为对象A不再需要关注它自己的依赖关系的初始化。对象B根据配置或期望的行为来决定向对象A提供哪些实现。
对于扩展开发者来说,这是一个需要理解的重要概念,因为它构成了Magento如何组成其类的基础。
Dependency inversion principle
遵循依赖性倒置原则,在你的代码中使用抽象来减少代码的依赖性。这意味着你的高层类应该使用低层类的接口,而不是直接使用它们。
在你的代码中使用接口可以减少Magento改变这些接口的底层实现时出现不兼容错误的风险。它还能让你专注于一个类的作用,而不是它的实现方式。
由于Magento代码库遵循这一原则,你可以使用di.xml文件将你自己对Magento接口的实现映射到依赖类或服务上。
Object manager 对象管理器
ObjectManager是Magento的一个服务类,它在引导过程的开始阶段对对象进行实例化。
Magento使用类的构造函数签名来检索关于一个对象的构造函数依赖的信息。当一个类被构建时,对象管理器会将定义在di.xml文件中的该类的依赖关系注入到该类的构建器中。
由于对象管理器间接地提供它的服务,你的类不应该依赖ObjectManager对象本身。唯一的例外是具有复杂逻辑的自定义工厂和需要环境设置的集成测试。
Compiling dependencies 依赖编译
Magento使用其代码编译器工具来收集所有的类依赖信息,并将其存储在文件中。在类的创建过程中,对象管理器使用这些信息来创建应用程序中的具体对象。
代码库中不存在的服务类,如代码中或配置中声明的代理、工厂和拦截器,在编译器的帮助下生成。
Injection types used in Magento
The following code sample highlights the two types of dependency injections used in Magento:
namespace Magento\Backend\Model\Menu;
class Builder
{
/**
* @var \Magento\Backend\Model\Menu\Item\Factory
*/
private $_itemFactory;
/**
* @param \Magento\Backend\Model\Menu\Item\Factory $menuItemFactory
*/
public function __construct(
\Magento\Backend\Model\Menu\Item\Factory $menuItemFactory, // Service dependency
) {
$this->_itemFactory = $menuItemFactory;
}
/**
* @param \Magento\Backend\Model\Menu\Builder\AbstractCommand
*/
public function processCommand(\Magento\Backend\Model\Menu\Builder\AbstractCommand $command) // API param
{
// processCommand Code
}
}
Constructor injection
在代码示例中,Builder类在其构造函数中声明了它对Factory和Menu类的依赖性。Magento使用di.xml文件来决定哪些实现要注入到Builder类中。
可选的依赖性 可选的依赖是你的类在特定的方法和情况下使用的对象。如果一个类的实例化费用很高,而且你的类并不总是使用它,可以考虑使用代理。
你必须对一个对象的所有可选和必需的依赖性使用构造器依赖性注入。
Method injection
在代码示例中,Builder类也依赖于AbstractCommand类的processCommand()方法。
方法注入涉及到将一个依赖关系作为方法参数传入,以便在类的逻辑中使用它。当一个对象需要对一个不能被注入的依赖关系执行操作时,可以使用方法注入。
Dependency types
Injectable
可注入对象是通过依赖性注入获得的单子服务对象。对象管理器使用di.xml文件中的配置来创建这些对象,并将其注入构造函数。
可注入对象可以在其构造函数中依赖其他可注入对象,只要依赖链不回溯到原始可注入对象。
Newable/non-injectable
可注入(Newable)或不可注入(Non-injectable)对象是不能被注入的对象。每次需要它们的时候,它们都是通过创建一个新的类实例来获得。
暂时性的对象,例如那些需要来自用户或数据库的外部输入的对象,就属于这个类别。如果你试图注入这些对象,你将会收到一个不完整的、不正确的对象或者一个错误,即该对象无法被创建。
例如,你不能依赖一个模型对象,如Product,因为你需要提供一个产品ID或明确请求一个新的、空的实例来获得一个Product对象。由于你不能在构造函数签名中指定这些数据,Magento不能注入这个对象。
为了绕过这个限制,可注入对象可以依赖于产生可更新对象的工厂。