Então, eu sei teoricamente o que é uma classe proxy no Magento 2. Eu li o incrível artigo de Alan Storm sobre isso e compreendo perfeitamente como essas classes são geradas.
No entanto, e não sei se é porque não sou um falante nativo de inglês ou se as explicações de Alan estão usando classes não essenciais que são muito abstratas, mas estou tendo dificuldade para entender como funciona e especialmente quando usar durante o desenvolvimento.
Então, vamos pegar este exemplo do núcleo em app/code/Magento/GoogleAdwords/etc/di.xml
:
<?xml version="1.0"?>
<!--
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\GoogleAdwords\Observer\SetConversionValueObserver">
<arguments>
<argument name="collection" xsi:type="object">Magento\Sales\Model\ResourceModel\Order\Collection\Proxy</argument>
</arguments>
</type>
</config>
Eu gostaria de saber:
- por que uma classe proxy é usada nesse caso específico?
- quando, em geral, alguém deve usar uma classe proxy?
fonte
Uma classe proxy permite injetar dependência em uma classe que você não precisará necessariamente, e que tem um alto custo associado a isso.
Se você olhar para um proxy que o Magento gerou, por exemplo
\Magento\Framework\View\Layout\Proxy
, verá que ele tem todos os mesmos métodos da classe original. A diferença é que toda vez que um desses é chamado, ele verifica se a classe de que é um proxy foi realmente instanciada e cria o objeto, se não. (Isso acontece em um_getSubject()
ou_getCache()
método.)É carregamento lento para injeção de dependência.
Você deve usar um proxy se uma dependência de classe nem sempre for usada por sua classe e:
Um bom exemplo disso são as sessões. Conseguir sessões através do ObjectManager é uma prática ruim, mas injetar uma classe de sessão como
\Magento\Customer\Model\Session
poderia quebrar as coisas se sua classe fosse executada fora do escopo dessa sessão (digamos que você injete a sessão do cliente front-end em uma página de administrador). Você contorna isso injetando o proxy da sessão\Magento\Customer\Model\Session\Proxy
e referenciando-o apenas quando você sabe que é válido. A menos que você faça referência a ela, a sessão nunca será instanciada e nada será interrompido.No seu exemplo específico
di.xml
, parece que eles usaram o proxy para justificar a injeção de um controlador em vez da fábrica desse controlador. De qualquer maneira, não é para isso que os proxies devem ser usados, e o benefício dele nessa situação é provavelmente mínimo.fonte
Os proxies gerados automaticamente do tipo Magento 2 podem ser usados para "corrigir" erros de design. Isso pode ser muito útil. Existem 2 casos de uso:
Envolva um gráfico de objeto caro que pode não ser necessário todas as vezes pelo dependente.
Quebre uma dependência cíclica em que a classe
A
dependeB
e a classeB
depende umA
.A injeção
B\Proxy
noA
permite instanciarA
, que por sua vez pode ser usado para instanciarB
quando é realmente usado com oA
objeto real .Em caso de 1. a dependência que nem sempre é usada é um sinal de que a classe dependente faz muito, ou talvez faz muito por um método. O comando do console @ivan mencionado é um bom exemplo disso.
No caso de 2. Não conheço uma maneira genérica de acabar com essa dependência. Costumo reescrever se houver tempo, mas isso pode não ser uma opção.
Apenas como uma observação lateral, gostaria de acrescentar que existem muitos mais tipos de proxies no OOP do que a instanciação lenta gerada automaticamente que o Magento 2 usa (por exemplo, proxy remoto).
fonte
Aqui estão as respostas
por que uma classe proxy é usada nesse caso específico?
Se você examinar atentamente o código escrito para a classe "SetConversionValueObserver", se o Google adwards não estiver ativo "return" e se não houver pedido "return". Significa que o Objeto de coleta de pedidos será criado apenas quando os IDs de pedidos existirem e o Google AdWords ativo. se injetarmos a classe de coleção de pedidos real, o gerenciador de objetos criará o objeto de coleção com seus objetos de classe pai sem saber que o Google AdWords não está ativo e essa página de êxito do pedido será mais lenta. portanto, crie melhor o objeto sob demanda, que é o uso de proxy. /vendor/magento/module-google-adwords/Observer/SetConversionValueObserver.php
quando, em geral, alguém deve usar uma classe proxy? - Injetar classe Proxy quando você achar que a criação de objetos será cara e o construtor da classe consumir muito recursos. - quando você não deseja um impacto desnecessário no desempenho devido à criação do objeto. - quando você acha que a criação de objetos deve acontecer quando você chama um método específico em uma condição específica nem sempre. Por exemplo, o construtor Layout é um recurso intensivo.
Construtor de layout real vs layout / proxy
Construtor proxy, dê uma olhada, nenhum construtor pai chamado e apenas passou o nome da classe de layout para que a criação real do objeto aconteça quando o método for chamado.
A classe proxy possui um método para criar objeto sob demanda, _subject é o objeto da classe passada.
E método chamado usando _subject.
fonte