Entonces, sé teóricamente qué es una clase proxy en Magento 2. Leí el increíble artículo de Alan Storm sobre él y entiendo totalmente cómo se generan esas clases.
Sin embargo, y no sé si es porque soy un hablante no nativo de inglés o si las explicaciones de Alan están usando clases no básicas que son muy abstractas, pero me cuesta entender cómo funciona y especialmente cuándo usar durante el desarrollo
Así que tomemos este ejemplo del núcleo en 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>
Me gustaría saber:
- ¿Por qué se usa una clase proxy en ese caso particular?
- ¿Cuándo, en general, se debe usar una clase proxy?
fuente
Una clase proxy le permite inyectar una clase de dependencia que no necesariamente necesitará, y que tiene un alto costo asociado con hacerlo.
Si observa un proxy que Magento ha generado,
\Magento\Framework\View\Layout\Proxy
verá que tiene los mismos métodos que la clase original. La diferencia es que cada vez que se llama a alguno de ellos, comprueba si la clase de la que es un proxy realmente se ha instanciado y crea el objeto si no. (Esto sucede en un_getSubject()
o_getCache()
método ).Es una carga lenta para la inyección de dependencia.
Debe usar un proxy si su clase no siempre utiliza una dependencia de clase y:
Un buen ejemplo de esto son las sesiones. Obtener sesiones a través del ObjectManager es una mala práctica, pero inyectar una clase de sesión como
\Magento\Customer\Model\Session
podría romper las cosas si su clase alguna vez se ejecuta fuera del alcance de esa sesión (digamos que inyecta la sesión de cliente frontend en una página de administración). Lo solucionas inyectando el proxy de la sesión\Magento\Customer\Model\Session\Proxy
y solo haga referencia a él cuando sepa que es válido. A menos que lo haga referencia, la sesión nunca se instancia y nada se rompe.En su ejemplo específico de
di.xml
, parece que usaron el proxy para justificar la inyección de un controlador en lugar de la fábrica de ese controlador. De cualquier manera, eso no es para lo que se pretende usar los proxies, y el beneficio de ello en esa situación es probablemente mínimo.fuente
Los proxies autogenerados de tipo Magento 2 se pueden usar para "corregir" errores de diseño. Eso puede ser muy útil. Hay 2 casos de uso:
Envuelva un gráfico de objetos caros que la persona dependiente podría no necesitar cada vez.
Romper una dependencia cíclica donde la clase
A
dependeB
y la claseB
depende de unA
.La inyección
B\Proxy
enA
le permite instantiateA
, que luego a su vez puede ser utilizado para crear una instanciaB
cuando se utiliza realmente con el verdaderoA
objeto.En el caso de 1. la dependencia que no siempre se usa es una señal de que la clase dependiente hace demasiado, o tal vez hace demasiado por un método. El comando de consola @ivan mencionado es un buen ejemplo de eso.
En el caso de 2. No conozco una forma genérica de romper esa dependencia. Tiendo a reescribir si hay tiempo, pero eso podría no ser una opción.
Solo como nota al margen, me gustaría agregar que hay muchos más tipos de proxies en OOP que la instanciación perezosa autogenerada que usa Magento 2 (por ejemplo, proxy remoto).
fuente
Aquí están las respuestas
¿Por qué se usa una clase proxy en ese caso particular?
Si observa de cerca el código que está escrito para la clase "SetConversionValueObserver", si Google Adwards no está activo "return" y si no hay ningún pedido "return". Significa que el objeto de recopilación de pedidos se creará solo cuando existan identificadores de pedido y los adwords de Google estén activos. si inyectamos la clase de colección de pedidos real, el administrador de objetos crea un objeto de colección con sus objetos de clase principal sin saber que los adwords de Google no están activos y que ralentizan la página de éxito del pedido. por lo tanto, mejor crear objetos a pedido que es el uso de proxy. /vendor/magento/module-google-adwords/Observer/SetConversionValueObserver.php
¿Cuándo, en general, se debe usar una clase proxy? - Inyecte la clase Proxy cuando crea que la creación de objetos será costosa y que el constructor de la clase es particularmente intensivo en recursos. - cuando no desea un impacto innecesario en el rendimiento debido a la creación de objetos. - cuando sienta que la creación de objetos debería ocurrir cuando llama a un método particular en una condición particular, no siempre. Por ejemplo, el constructor Layout requiere muchos recursos.
Real Layout constructor vs layout / proxy
Proxy constructor, eche un vistazo, no se llama al constructor padre, así como solo se pasa el nombre de la clase de diseño para que la creación real del objeto ocurra cuando se llama al método.
La clase proxy tiene un método para crear objetos a pedido, _subject es el objeto de la clase pasada.
Y método llamado usando _subject.
fuente