Я не понимаю, почему в некоторых классах их инъекции зависимостей объявляются дважды - один раз в конструкторе di.xml
и в конкретном классе.
Например, в Magento\Backend\Model\Url
его di.xml
определен набор типов для DI:
<type name="Magento\Backend\Model\Url">
<arguments>
<argument name="scopeResolver" xsi:type="object">
Magento\Backend\Model\Url\ScopeResolver</argument>
<argument name="authSession" xsi:type="object">
Magento\Backend\Model\Auth\Session\Proxy</argument>
<argument name="formKey" xsi:type="object">
Magento\Framework\Data\Form\FormKey\Proxy</argument>
<argument name="scopeType" xsi:type="const">
Magento\Store\Model\ScopeInterface::SCOPE_STORE </argument>
<argument name="backendHelper" xsi:type="object">
Magento\Backend\Helper\Data\Proxy</argument>
</arguments>
</type>
Но в то же время в его конкретном классе те классы, определенные в di.xml, которые необходимы для внедрения, снова объявляются в конструкторе:
<?php
public function __construct(
\Magento\Framework\App\Route\ConfigInterface $routeConfig,
\Magento\Framework\App\RequestInterface $request,
\Magento\Framework\Url\SecurityInfoInterface $urlSecurityInfo,
\Magento\Framework\Url\ScopeResolverInterface $scopeResolver,
\Magento\Framework\Session\Generic $session,
\Magento\Framework\Session\SidResolverInterface $sidResolver,
\Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolverFactory,
\Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
$scopeType,
\Magento\Backend\Helper\Data $backendHelper,
\Magento\Backend\Model\Menu\Config $menuConfig,
\Magento\Framework\App\CacheInterface $cache,
\Magento\Backend\Model\Auth\Session $authSession,
\Magento\Framework\Encryption\EncryptorInterface $encryptor,
\Magento\Store\Model\StoreFactory $storeFactory,
\Magento\Framework\Data\Form\FormKey $formKey,
array $data = []
) {
//...
}
?>
Если мы посмотрим на его конструктор выше, \Magento\Framework\App\Route\ConfigInterface $routeConfig
например, не определен в di.xml
. Он определен только в конструкторе, и Magento по-прежнему внедрит его routeConfig
в класс для использования, не так ли? То же самое \Magento\Framework\Encryption\EncryptorInterface $encryptor
и несколько других.
Тогда, почему существует необходимость определять другие внедрения в обоих di.xml
и в конструкторе, когда наличия этих объявлений в конструкторе достаточно для Magento, чтобы внедрить эти зависимости в класс для использования?
Важно понимать разницу между определением зависимостей и настройкой зависимостей.
Зависимости не определены внутри di.xml. Зависимости определяются внутри конструктора соответствующего класса путем указания интерфейса, реферата или фабрики в качестве типа этой конкретной зависимости, например,
$routeConfig
зависимости типа\Magento\Framework\App\Route\ConfigInterface
.С другой стороны,
di.xml
это место для настройки зависимостей с использованием<preference/>
узлов и / илиxpath:type/arguments/argument
узлов (иногда в сочетании с более сложными узлами конфигурации, такими как<virtualType/>
или<proxy/>
). Настройка зависимости просто означает сопоставление аргумента конструктора объекта с реализацией / объектом / конкретным .Вы хотите, чтобы зависимости конфигурировались с помощью di.xml, чтобы вы могли поменять их местами и использовать другую реализацию для определенного интерфейса или аргумента при определенных условиях (продолжайте читать пример, чтобы понять, что должны означать определенные условия).
Например, при разработке вашего расширения вы сначала должны создать новый класс (мы называем этот новый класс реализацией ). Ваш новый класс реализует
\Magento\Framework\App\Route\ConfigInterface
интерфейс, и в его теле есть конкретная функциональность, которая выполняет контракт интерфейса. Теперь запускаем часть конфигурации : чтобы указать Magento использовать вашу недавно определенную реализацию, вы должны сконфигурировать эту реализацию как зависимость для объектаMagento\Backend\Model\Url
. Вы делаете эту конфигурацию внутриdi.xml
файлов или вашего модуля. В этом случае вам нужно использовать<preference/>
узел для сопоставления интерфейса с вашей новой реализацией. В других случаях вы бы использовали более гранулированныйxpath:type/arguments/argument
di.xml
узел дляотображать только конкретные аргументы (или зависимости, или интерфейсы) конкретного объекта в конкретные реализации . Теперь ваша реализация будет активна в качестве зависимости для объекта только\Magento\Backend\Model\Url
в определенных условиях , например, в потоке выполнения кода текущего запроса приложения создается объект типаMagento\Backend\Model\Url
, и требуется реализация для определенной конструктором зависимости,$routeConfig
которая называется типа\Magento\Framework\App\Route\ConfigInterface
.Это почти как сказать:
«Привет, мистер ObjectManager! Всякий раз, когда
Magento\Backend\Model\Url
запрашивается экземпляр объекта типа , сначала посмотрите на его определение конструктора класса и проанализируйте определенные в нем зависимости . Я хочу, чтобы вы затем посмотрели в окончательном объединенномdi.xml
текущем HTTP-запросе конфигурацию для каждой настроенной зависимости , определенной в конструкторе класса Magento \ Backend \ Model \ Url . Вы даете мне эту настроенную реализацию зависимости. "источник