<h5 style="color:red;">系统学习magento二次开发,推荐小册:<a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank">《Magento中文全栈二次开发
》</a></h5>
<div class="image-container">
<p>
<a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank">
<img src="https://www.maxiaoke.com/uploads/images/20230218/bb9c82995c24d1105676e02f373755f5.jpg" alt="Magento中文全栈二次开发">
</a>
</p>
</div>
<div class="text-container" style="font-size:14px; color:#888">
<p>本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。</p>
</div>
<hr><p>magento2中的proxy是一种设计模式,比较难于理解,本篇内容将为大家介绍magento2中的代理模式:proxy<br/></p><p><span style="text-wrap: nowrap;">当对象创建成本很高,并且类的构造函数占用了大量资源时,就会使用代理类。为了避免不必要的性能影响,</span></p><p><span style="text-wrap: nowrap;">Magento使用Proxy类将给定的类型变成它们的延迟加载版本。</span></p><p><span style="text-wrap: nowrap;">在所有Magento di.xml文件中快速查找\Proxy</argument>字符串可以发现该字符串出现了一百多次。</span></p><p><span style="text-wrap: nowrap;">可以说,Magento在其代码中广泛使用代理。</span></p><p><span style="text-wrap: nowrap;"><MAGENTO_DIR>/module-customer/etc/di.xml下的类型定义是使用代理的一个很好的例子:</span></p><pre class="brush:bash;toolbar:false"><type name="Magento\Customer\Model\Session">
<arguments>
<argument name="configShare" xsi:type="object">Magento\Customer\Model\Config\Share\Proxy</argument>
<argument name="customerUrl" xsi:type="object">Magento\Customer\Model\Url\Proxy</argument>
<argument name="customerResource" xsi:type="object">Magento\Customer\Model\ResourceModel\Customer\Proxy</argument>
<argument name="storage" xsi:type="object">Magento\Customer\Model\Session\Storage</argument>
<argument name="customerRepository" xsi:type="object">Magento\Customer\Api\CustomerRepositoryInterface\Proxy</argument>
</arguments>
</type></pre><p><span style="text-wrap: nowrap;">如果我们查看Magento\Customer\Model\Session类型的构造函数,我们可以看到四个参数</span></p><p><span style="text-wrap: nowrap;">(configShare、customerUrl、customerResource和customerRepository)中,</span></p><p><span style="text-wrap: nowrap;">没有一个在PHP文件中声明为Proxy。</span><span style="text-wrap: nowrap;">它们是通过di.xml重写的。</span></p><p><span style="text-wrap: nowrap;">这些代理类型还不真正存在,因为Magento依赖注入(di)编译过程创建了它们。</span></p><p><span style="text-wrap: nowrap;">它们是在生成的目录下自动生成的。</span></p><p><span style="text-wrap: nowrap;">编译后,可以在生成的/code/Magento/Customer/Model/Url/Proxy.php</span></p><p><span style="text-wrap: nowrap;">文件下轻松找到Magento\Customer\Model\Url\Proxy.php类型。</span></p><p><span style="text-wrap: nowrap;">让我们局部来看一下:</span></p><pre class="brush:bash;toolbar:false"><?php
class Proxy extends\ Magento\ Customer\ Model\ Url implements\ Magento\ Framework\ ObjectManager\ NoninterceptableInterface {
public function __construct(\Magento\ Framework\ ObjectManagerInterface $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 = \Magento\ Framework\ App\ ObjectManager::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();
}
}</pre><p><span style="text-wrap: nowrap;">Proxy类的组成显示了它包装原始Magento\Customer\Model\Url类型的机制。这意味着,在整个Magento中,</span></p><p><span style="text-wrap: nowrap;">每次请求Magento\Customer\Model\Url类型时,</span></p><p><span style="text-wrap: nowrap;">Magento\Customer\Module\Url\Proxy都会被传递。与原始类型的__construct方法(可能会影响性能)不同,</span></p><p><span style="text-wrap: nowrap;">自动生成代理的__construction方法是轻量级的。</span><span style="text-wrap: nowrap;">这消除了可能的性能瓶颈。_getSubject方法用于在调用任何原始类型的公共方法时,</span></p><p><span style="text-wrap: nowrap;">实例化/延迟加载原始类型。</span></p><p><span style="text-wrap: nowrap;">例如,对getLoginUrl方法的调用将通过代理。</span></p><p><span style="text-wrap: nowrap;">Magento生成的每个代理都实现了Magento\Framework\ObjectManager\NoninterceptableInterface。</span></p><p><span style="text-wrap: nowrap;">尽管接口本身是空的,但它被用作标识代理的标记,</span></p><p><span style="text-wrap: nowrap;">我们不需要为其生成拦截器(插件)。</span></p><pre class="brush:bash;toolbar:false">class Customer {
public
function __construct(\Magento\ Customer\ Model\ Url\ Proxy $customerUrl) { //... }}</pre><p><span style="text-wrap: nowrap;"></span></p><p><span style="text-wrap: nowrap;">然而,这种做法是一种糟糕的做法。正确执行此操作的方法是使用原始Magento\Customer\Model\Url类型指定__construct,</span></p><p><span style="text-wrap: nowrap;">然后按如下方式添加di.xml:</span></p><pre class="brush:bash;toolbar:false"><type name="Magelicious\Core\Model\Customer">
<arguments>
<argument name="customerUrl" xsi:type="object">Magento\Customer\Model\Url\Proxy</argument>
</arguments>
</type></pre><p><span style="text-wrap: nowrap;"></span></p><p><span style="text-wrap: nowrap;"></span></p>