Yii2 實例管理

Yii2 實例管理

Yii2框架沒有提供類似ZendFramework3中提供的ServiceManager.那么Yii2框架是如何管理對象實例的呢?

長時間使用Yii2框架的童鞋一定已經(jīng)適應(yīng)了對象中的public變量,以及一個來自yii\base\Component的__set()魔術(shù)方法來完成對象構(gòu)造的過程,但是新鳥如何使用這一切來實例化一個對象呢?

Yii2最擅長的是extends多個對象使他們擁有多個父類的特征.那么習(xí)慣了ZendFramework3這種純粹OOP的童鞋,有沒有方法既可以盡快適應(yīng)Yii2的簡約,又堅定的不侵犯對象變量的私有性,甚至還能優(yōu)雅的用注入取代繼承呢?

以下比較對象默認(rèn)為ZendFramework3.

Yii2 對象的實例化

在ZendFramework3中,對象的實例化是我見過相對復(fù)雜的.

  1. 首先ServiceManager會讀取所有已配置模塊的Module對象(每個模塊提供給ServiceManager的入口),并根據(jù)loadModules,loadModule等事件,以特定(可配置的,通過引用不同的內(nèi)置Interface)方式獲取模塊配置文件.
  2. 獲得配置文件時,ServiceManager會檢查依賴(如果需要).
  3. 一切順利后,ServiceManager會依照配置文件,尋找這個模塊或類的工廠.工廠是一個callable,可以極其復(fù)雜,因為每個工廠會接受到整個項目的容器,也就是ServiceManager,也可以是簡單的內(nèi)置,InvokeFactory.
  4. 最終ServiceManager會自動的將工廠的產(chǎn)品,也就是這個模塊的實例緩存到自身的變量中,以便全局可以訪問.

可見ServiceManager是一個綜合體,用于對象實例的管理,充當(dāng)全局容器(里面甚至包含所有的配置文件和事件管理模塊等所有框架的內(nèi)核).

你肯定會擔(dān)心性能損耗,在小型項目中這種損耗是有的,就像快速排序,面對大宗數(shù)據(jù)才是它大展身手的時候.也就是說,隨著項目體量的增加,這種損耗的遞增會遠(yuǎn)遠(yuǎn)低于體量的遞增.

缺點:學(xué)習(xí)成本很高.


那么Yii2中有這樣的機(jī)制嗎?答曰,有.

Yii2中居然用一個近似讓人啼笑皆非的方式解決了這個全局容器的需求.就是那個哪里都能看到的靜態(tài)調(diào)用Yii.

use Yii;

很聰明!但是缺少了保障:

  1. 安全性.對于全部項目,Yii這個容器始終是可見的,沒有注入的安全性,不注入你休想碰全局.Yii2的問題在于安全,尤其是多人開發(fā)的項目,例如通過Yii::$app->user->setIdentity($identity);輕松改變框架的當(dāng)前登錄用戶,偽造當(dāng)前用戶.

  2. 穩(wěn)定性.這個是我的猜測,將整個框架直接交給一個Yii,真的好嗎?做法等同于將整個框架放入了一個PHP數(shù)組,并且這還是個全局的數(shù)組.

優(yōu)點:學(xué)習(xí)成本很低.


Yii2在設(shè)計上表達(dá)了一個簡單粗暴的觀點,簡單大于一切,甚至性能!

Yii2在對象的實例化時居然使用了Reflection[淚目.jpg],你沒有看錯,就是那個性能如老狗的反射.為什么呢?

就為了讓你少些代碼.

Yii::createObject([
    'class' => 'foo\bar',
    'name'  => 'Bob'
]);

以上代碼實例化了一個foo\bar;對象,并執(zhí)行了$bar->name = 'Bob';,怎么樣,是不是很簡單?這一切都是Reflection的功勞.當(dāng)然Yii::createObject()還有一下用法,更加神奇.

//In foo/bar.php

class bar
{
    public function __construct(SomeInterface $param1, $param2 = 'nothing')
    {
        //something to do.
    }
}

//In some place.

Yii::createObject('foo\bar', [
    'param1' => $someClass,//instance from SomeInterface
])

可見.Yii::createObject()還可以對你的__construct賦值.不但會檢查參數(shù)列表的默認(rèn)值,對象類型,而且還會為提供可變參數(shù)的構(gòu)造函數(shù)檢查PHP'版本.很貼心有木有?

但是這一切都是Reflection提供的.也是在PHP應(yīng)用層能解決的唯一途徑.

在動不動就實例化幾百個對象的應(yīng)用中,如果追求性能極致的小伙伴,最好還是自己實現(xiàn)實例管理工具.我也會在后續(xù)的空閑時間實現(xiàn)這個功能,請關(guān)注本人GitHub.

Yii2 對象實例的緩存

var_dump(Yii::$container->get(Test::class) === Yii::$container->get(Test::class));

上例返回false[懵逼.jpg],怎么回事,Yii2不緩存對象嗎?那么Yii2的單例如何實現(xiàn)呢?

原來,Yii2中你要想讓自己的對象被緩存,只有先Yii::$container->set(),再Yii::$container->get().setget的參數(shù)列表是對稱的.

也就是說,Yii2不會自動給你緩存對象,實現(xiàn)單例.可能是怕誤導(dǎo)不知道設(shè)計模式的初學(xué)者,為了對新手友好吧.

setget的具體用法在\yii\di\Container的注釋中有非誠詳細(xì)的說明.

值得一說的是,作者也意識到頻繁的使用Reflection對性能的影響,所以在每次實例化的時候會自動的緩存對象的Reflection.這點還是非常溫馨的.


Yii2中最常見的實例化對象的方法

Yii::createObject();

這個東西,這其實只是簡單的對yii\di\Containreget()的封裝.

這個方法有兩個參數(shù):

  1. 對象設(shè)置
    這是個數(shù)組,除了'class' => 'SomeClass'表示這個類的名字外,其他全部代表這個類的屬性.
  2. constructor參數(shù)列表
    這個沒有什么好解釋的,就是構(gòu)造函數(shù)的參數(shù)列表寫成數(shù)組的形式而已.

總結(jié)

其實作文還沒有寫完,我并沒有去yy怎樣去自己實現(xiàn)一個實例容器模塊.因為我想在模塊出現(xiàn)在GitHub上的時候,結(jié)合README詳細(xì)說明.并在以后的開發(fā)中不斷改進(jìn).

毫無疑問,Yii2是個非常精妙的框架,脾氣也非常清晰,易用大于一切,畢竟用框架開發(fā)的項目不會是超大項目.如果追求性能上的極致,可能任何框架都沒法滿足你的要求,甚至是PHP本身.到那時候的討論可能涉及到更深的層次.就目前而言,就目前的應(yīng)用層次,看待每一個框架,你會發(fā)現(xiàn)每個作者的思想都有很獨特的地方,可能這個思想本身就已經(jīng)大于框架本身的意義了,尤其是每個作者展現(xiàn)給我們的,在現(xiàn)實和理想沖突的時候,做出的妥協(xié).

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • date: 2017-11-21 18:15:18title: yii 源碼解讀 百度腦圖 - yii 源碼解析:...
    daydaygo閱讀 3,601評論 1 11
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,034評論 25 709
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,692評論 18 399
  • Sites 網(wǎng)站 yiifeed:Yii 最新動態(tài)都在這里 yiigist:Yii 專用的 Packages my...
    guanguans閱讀 2,693評論 0 11
  • 原貼 在安裝過程中發(fā)現(xiàn)問題 一、安裝Parallels Desktop Parallels Desktop 號稱M...
    表象_Dark閱讀 10,844評論 0 2

友情鏈接更多精彩內(nèi)容