Proxies

Proxy classes are used when object creation is expensive and a class' constructor is unusually resource-intensive. To avoid unnecessary performance impact, Magento uses Proxy classes to turn given types into becoming lazy-loaded versions of them.

A quick lookup for the Proxy</argument> string across all Magento di.xml files reveals over a hundred occurrences of this string. It goes to say that Magento extensively uses proxies across its code.

The type definition under <MAGENTO_DIR>/module-customer/etc/di.xml is a nice example of using proxies:

<type name="MagentoCustomerModelSession">
<arguments>
<argument name="configShare" xsi:type="object">MagentoCustomerModelConfigShareProxy</argument>
<argument name="customerUrl" xsi:type="object">MagentoCustomerModelUrlProxy</argument>
<argument name="customerResource" xsi:type="object">MagentoCustomerModelResourceModelCustomerProxy</argument>
<argument name="storage" xsi:type="object">MagentoCustomerModelSessionStorage</argument>
<argument name="customerRepository" xsi:type="object">MagentoCustomerApiCustomerRepositoryInterfaceProxy</argument>
</arguments>
</type>

If we look at the constructor of the MagentoCustomerModelSession type, we can see that none of the four arguments (configShare, customerUrl, customerResource, and customerRepository) were declared as Proxy within the PHP file. They where rewritten through di.xml. These Proxy types do not really exist just yet, as the Magento dependency injection (di) compilation process creates them. They are automatically generated under the generated directory.

Once it is compiled, the MagentoCustomerModelUrlProxy type can easily be found under the generated/code/Magento/Customer/Model/Url/Proxy.php file. Let's take a partial look at it:

class Proxy extends MagentoCustomerModelUrl 
implements MagentoFrameworkObjectManagerNoninterceptableInterface {
public function __construct(
MagentoFrameworkObjectManagerInterface $objectManager,
$instanceName = '\Magento\Customer\Model\Url',
$shared = true) {
$this->_objectManager = $objectManager;
$this->_instanceName = $instanceName;
$this->_isShared = $shared;
}

public function __sleep() {
return ['_subject', '_isShared', '_instanceName'];
}

public function __wakeup() {
$this->_objectManager = MagentoFrameworkAppObjectManager::getInstance();
}

public function __clone() {
$this->_subject = clone $this->_getSubject();
}

protected function _getSubject() {
if (!$this->_subject) {
$this->_subject = true === $this->_isShared
? $this->_objectManager->get($this->_instanceName)
: $this->_objectManager->create($this->_instanceName);
}
return $this->_subject;
}

public function getLoginUrl() {
return $this->_getSubject()->getLoginUrl();
}

public function getLoginUrlParams() {
return $this->_getSubject()->getLoginUrlParams();
}
}

The composition of the Proxy class shows the mechanism by which it wraps around the original MagentoCustomerModelUrl type. This now means that, across Magento, every time the MagentoCustomerModelUrl type is requested, the MagentoCustomerModelUrlProxy is going to get passed instead. Unlike the original type's __construct method which might be performance heavy, the autogenerated Proxy's __construct method is a lightweight one. This eliminates possible performance bottlenecks. The _getSubject method is used to instantiate/lazy load the original type whenever any of the original type public methods are called. For example, the call to the getLoginUrl method would go through the proxy.

Every proxy generated by Magento implements MagentoFrameworkObjectManagerNoninterceptableInterface. Though the interface itself is empty, it is used as a marker to identify proxies for which we don't need to generate interceptors (plugins).

When writing custom types, such as MageliciousCoreModelCustomer, we could easily specify the proxy right there in the constructor:

class Customer {
public function __construct(
MagentoCustomerModelUrlProxy $customerUrl
) {
//...
}
}

This approach, however, is a bad practice. The way to do this properly is to specify __construct with an original MagentoCustomerModelUrl type and then add the di.xml as follows:

<type name="MageliciousCoreModelCustomer">
<arguments>
<argument name="customerUrl" xsi:type="object">MagentoCustomerModelUrlProxy</argument>
</arguments>
</type>
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.254.122