Perché alcune classi definiscono iniezioni sia nel loro costruttore che in di.xml?


12

Non capisco perché, in alcune classi, le loro iniezioni di dipendenza siano dichiarate due volte - una volta nella di.xmle nel costruttore della classe concreta.

Ad esempio in Magento\Backend\Model\Url, di.xmlha questo set di tipi per DI definito:

<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>

Ma allo stesso tempo, nella sua classe concreta, quelle classi definite in di.xml richieste per l'iniezione vengono nuovamente dichiarate nel costruttore:

<?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 = []
) {
    //...
}
?>

Se guardiamo il suo costruttore sopra \Magento\Framework\App\Route\ConfigInterface $routeConfig, per esempio, non è definito in di.xml. È definito solo nel costruttore e Magento continuerà a iniettarlo routeConfignella classe per l'uso, no? Lo stesso per \Magento\Framework\Encryption\EncryptorInterface $encryptore pochi altri.

Quindi, perché è necessario definire le altre iniezioni in entrambi di.xmle nel costruttore quando avere tali dichiarazioni nel costruttore è sufficiente affinché Magento possa iniettare quelle dipendenze nella classe per l'uso?

Risposte:


15

Come indicato nella documentazione , in Magento 2, è di.xmlpossibile utilizzare le seguenti operazioni:

Puoi configurare gli argomenti del costruttore della classe nel tuo di.xmlnel nodo argomento. Il gestore oggetti inserisce questi argomenti nella classe durante la creazione. Il nome dell'argomento configurato nel file XML deve corrispondere al nome del parametro nel costruttore nella classe configurata.

Nel tuo caso è leggermente complesso spiegherò ogni argomento uno per uno:

  • \Magento\Framework\App\Route\ConfigInterface $routeConfig: questa è un'interfaccia quindi non è utilizzabile direttamente . La preferenza per questa classe è definita inapp/etc/di.xml ed è la Magento\Framework\App\Route\Configclasse
  • \Magento\Framework\App\RequestInterface $request : lo stesso vale per questa classe, la preferenza è Magento\Framework\App\Request\Http
  • \Magento\Framework\Url\SecurityInfoInterface $urlSecurityInfo: stesso caso qui di nuovo con Magento\Framework\Url\SecurityInfo\Proxyla preferenza
  • \Magento\Framework\Url\ScopeResolverInterface $scopeResolver: qui iniziamo con la parte interessante. In app/etc/di.xmluna preferenza è definita per questa interfaccia ed è la Magento\Framework\Url\ScopeResolverclasse. Tuttavia, per Magento\Backend\Model\UrlMagento 2 è necessario utilizzare un'altra classe e quindi definisce quale classe nel di.xmltuo postato Magento\Backend\Model\Url\ScopeResolververrà utilizzata.
  • \Magento\Framework\Session\Generic $session questa è una classe normale e quindi può essere utilizzata come tale.
  • \Magento\Framework\Session\SidResolverInterface $sidResolver: torna a un'interfaccia, la preferenza è ancora definita in app/etc/di.xmle lo èMagento\Framework\Session\SidResolver\Proxy
  • \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolverFactory : questa è una classe di fabbrica quindi può essere utilizzata come tale.
  • \Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver: torniamo al nostro app/etc/di.xmle la preferenza èMagento\Framework\Url\QueryParamsResolver
  • \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig: un altro caso qui in cui ** è definita una preferenza app/etc/di.xmled è Magento\Framework\App\Config.
  • $scopeType: qui abbiamo solo una variabile senza alcuna classe. Il modulo di.xmlspecifica che Magento\Store\Model\ScopeInterface::SCOPE_STOREdeve essere utilizzato come valore di questa variabile. **
  • \Magento\Backend\Helper\Data $backendHelper: qui avremmo potuto usare quella classe così. Tuttavia, qui viene utilizzato un proxy perché questa classe non viene necessariamente utilizzata (vedere questo post per dettagli sulle classi proxy: Magento 2: spiegazione pratica di cos'è una classe proxy? )
  • \Magento\Backend\Model\Menu\Config $menuConfig : possiamo usare questa classe così com'è.
  • \Magento\Framework\App\CacheInterface $cache: un'altra preferenza definita app/etc/di.xmlper questa interfaccia che èMagento\Framework\App\Cache\Proxy
  • \Magento\Backend\Model\Auth\Session $authSession: lo stesso di nuovo qui avremmo potuto usare la classe ma usiamo invece una classe proxy per il caricamento lento.
  • \Magento\Framework\Encryption\EncryptorInterface $encryptor: saltando di app/etc/di.xmlnuovo e troviamo Magento\Framework\Encryption\Encryptorcome preferenza
  • \Magento\Store\Model\StoreFactory $storeFactory : una fabbrica in modo che possiamo usarla così.
  • \Magento\Framework\Data\Form\FormKey $formKey: qui usiamo di nuovo una Magento\Framework\Data\Form\FormKey\Proxyclasse proxy per il caricamento lento.
  • array $data = []: questo viene sempre l'ultimo ed è automaticamente impostato su un array vuoto, puoi trovare maggiori informazioni qui: Magento 2: qual è il parametro $ data array constructor?

Riassumere

A livello globale, i parametri dei costruttori di classi sono interfacce o classi non istanziabili. Pertanto, è di.xmlpossibile personalizzare le dipendenze che si desidera utilizzare per ciascun costruttore di classi. È valido anche per le classi istanziabili. Ad esempio un costruttore di classi che accetta una classe di prodotto come argomento del costruttore. Può essere personalizzato nel modulo di prodotto configurabile in modo da utilizzare una classe di prodotto configurabile come argomento.


È sempre richiesta una preferenza per un parametro di interfaccia? Può essere visto come un fallback? Ha senso definire un argomento concreto nella configurazione senza avere preferenze da nessuna parte? O non è possibile?
robsch,

6

È importante comprendere la differenza tra definizione delle dipendenze e configurazione delle dipendenze.

Le dipendenze non sono definite in di.xml. Le dipendenze sono definite all'interno del costruttore della rispettiva classe specificando un'interfaccia, un abstract o una factory come il tipo di quella specifica dipendenza, ad esempio $routeConfigè una dipendenza del tipo \Magento\Framework\App\Route\ConfigInterface.

D'altra parte, di.xmlè il posto dove configurare le dipendenze usando <preference/>nodi e / o xpath:type/arguments/argumentnodi (a volte accoppiati con nodi di configurazione più avanzati come <virtualType/>o <proxy/>). Configurare una dipendenza significa semplicemente mappare l'argomento del costruttore di un oggetto su un'implementazione / oggetto / calcestruzzo .

Volete che le dipendenze siano configurabili tramite di.xml in modo da poterle scambiare e usare un'implementazione diversa per una determinata interfaccia o argomento in determinate condizioni (continuate a leggere l'esempio per capire cosa dovrebbero significare determinate condizioni).

Ad esempio, quando sviluppi la tua estensione, devi prima creare una nuova classe (questa nuova classe viene definita un'implementazione ). La tua nuova classe implementa l' \Magento\Framework\App\Route\ConfigInterfaceinterfaccia e ha al suo interno una funzionalità concreta che onora il contratto di interfaccia. Ora inizia la parte di configurazione : per dire a Magento di usare l'implementazione appena definita, è necessario configurarla come dipendenza per l'oggetto Magento\Backend\Model\Url . Questa configurazione viene eseguita all'interno dei di.xmlfile o del modulo. In questo caso è necessario utilizzare il <preference/>nodo per mappare l'interfaccia alla nuova implementazione. Altre volte useresti il xpath:type/arguments/argument di.xmlnodo più granulare permappare solo argomenti specifici (noti anche come dipendenze, noti anche come interfacce) di una concreta implementazione specifica . Ora, l'implementazione sarà attiva come dipendenza per l'oggetto \Magento\Backend\Model\Url in determinate condizioni , ad esempio, nel flusso di esecuzione del codice della richiesta dell'applicazione corrente Magento\Backend\Model\Urlviene creato un oggetto di tipo e necessita di un'implementazione per la dipendenza definita dal costruttore chiamata $routeConfigche è di tipo \Magento\Framework\App\Route\ConfigInterface.

È quasi come dire:

"Ehi, signor ObjectManager! Ogni volta che Magento\Backend\Model\Urlviene richiesta un'istanza di oggetto di tipo , dai un'occhiata prima alla definizione del costruttore della sua classe e analizza le dipendenze ivi definite . Vorrei che cercassi all'interno della finale, unita di.xmlalla richiesta HTTP corrente la configurazione per ogni dipendenza configurato che viene definito nel costruttore della classe Magento \ backend \ modello \ Url . Tu mi dai quello configurato implementazione di dipendenza ".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.