php 自動加載原理

1. 自動加載與 Psr0陈哑、Psr4 和 Composer 的關(guān)系容诬?

說起PHP的自動加載,我們可能馬上想到的是各種框架的自動加載功能碟渺,PHP規(guī)范中的PSR0和PSR4原則, Composer 的自動加載功能等等突诬。PSR0和PSR4原則只是為我們定義自動加載的類提供了統(tǒng)一的規(guī)范苫拍,例如:命名空間芜繁,而 Composer 同樣是利用了這個統(tǒng)一規(guī)范加入了自動加載構(gòu)成一個完整的組件包,為我們的開發(fā)提供了很大的方便绒极。

2. 為什么會有自動加載

在PHP面向?qū)ο?OO)編程中骏令,為了方便管理,我們都會把一個類寫在一個單獨的文件中垄提,那么如果想在A類中使用B類的功能榔袋,就需要把B類加載到A類。對于這樣的需求在最原始的時候铡俐,我們是通過require 和 include 語法實現(xiàn)的摘昌。
PHP5實現(xiàn)了類的自動加載(Autoload)功能,減少傳統(tǒng)方式的文件引入方式帶來的復(fù)雜性高蜂,如:文件嵌套依賴聪黎、方法名沖突等。

3. __autoload()自動加載

PHP5實現(xiàn)了類的自動加載(Autoload)功能备恤,這個功能最初是通過PHP的一個魔術(shù)方法__autoload()實現(xiàn)的稿饰。后來,PHP擴展SPL(Standard PHP Library 標(biāo)準(zhǔn)PHP類庫)又實現(xiàn)了更強大的自動加載機制露泊。

我們需要明確__autoload()函數(shù)PHP在找不到類的時候會自動執(zhí)行喉镰,但是PHP內(nèi)部并沒有定義這個函數(shù),這個函數(shù)需要開發(fā)著自己定義惭笑,并且編寫內(nèi)部邏輯侣姆,PHP只負(fù)責(zé)在需要的時候自動調(diào)用執(zhí)行。而且在調(diào)用的時候會自動傳人要加載的類名作為參數(shù)沉噩。

4. __autoload()自動加載與SPL自動加載的關(guān)系

有了__autoload()函數(shù)捺宗,可以看出,如果我們現(xiàn)在需要引入100個其它文件川蒙,只需要訂好一個規(guī)則蚜厉,編寫一個函數(shù)就可以了。這比直接用require/inlude有了很大進步畜眨,但是同樣也有新的問題昼牛,在一個項目中,我們只能編寫一個__autoload()函數(shù)康聂,如果項目比較大贰健,加載每個文件都使用同樣的規(guī)則顯然是不現(xiàn)實的,那么我們可能就需要在__autoload()中編寫復(fù)雜的規(guī)則邏輯來滿足加載不同文件的需求恬汁。這同樣會使得__autoload()函數(shù)變得復(fù)雜臃腫伶椿,難以維護管理。
于是,SPL(Standard PHP Library 標(biāo)準(zhǔn)PHP類庫)的自動加載機制就應(yīng)時而生了悬垃。

5. SPL自動加載原理

首先游昼,明確一點甘苍,PHP在實例化一個對象時(實際上在實現(xiàn)接口尝蠕,使用類常數(shù)或類中的靜態(tài)變量,調(diào)用類中的靜態(tài)方法時都會如此)载庭,首先會在系統(tǒng)中查找該類(或接口)是否存在看彼,如果不存在的話就嘗試使用autoload機制來加載該類。而autoload機制的主要執(zhí)行過程為:
1囚聚、檢查執(zhí)行器全局變量函數(shù)指針autoload_func是否是NULL靖榕;
2、如果 autoload_func==NULL ,則查找系統(tǒng)是否定義 **__autoload() **函數(shù)顽铸,如果定義了茁计,則執(zhí)行并返回加載結(jié)果。如果沒有定義谓松,則報錯并退出星压;
3、如果 autoload_func 不等于NULL鬼譬,則直接執(zhí)行 autoload_func 指向的函數(shù)加載類娜膘,此時并不檢查 __autoload() 函數(shù)是否定義。

通過對PHP自動加載流程的了解优质,可以看到PHP實際上提供了兩種方法來實現(xiàn)自動裝載機制:
a. 一種我們前面已經(jīng)提到過竣贪,是使用用戶定義的__autoload()函數(shù),這通常在PHP源程序中來實現(xiàn)巩螃;
b. 另外一種就是設(shè)計一個函數(shù)演怎,將autoload_func指針指向它,這通常使用C語言在PHP擴展中實現(xiàn)避乏,即 SPL autoload機制颤枪。

如果兩種方式都實現(xiàn)了,也就是 autoload_func 不等于NULL淑际,程序只會執(zhí)行第二種方式畏纲,__autoload() 函數(shù)是不會被執(zhí)行的。

詳細(xì)分析SPL自動加載過程
假如把spl_autoload_register(’my_autoload’) 改成 spl_autoload_register()不添加任何參數(shù)春缕,B類能被加載嗎盗胀?答案是:YES。

為什么呢锄贼?
因為SPL擴展內(nèi)部自己定義了一個自動加載函數(shù) spl_autoload(),實現(xiàn)了自動加載的功能票灰,如果我們不定義自己的自動加載函數(shù),并且程序里寫了 spl_autoload_register()(如果不傳參數(shù),必須是第一次執(zhí)行才會有效)或者 spl_autoload_register(’spl_autoload’)屑迂,那么autoload_func 指針就會指向內(nèi)部函數(shù) spl_autoload()浸策。程序執(zhí)行的時候如果找不到相應(yīng)類就會執(zhí)行該自動加載函數(shù)。
那么惹盼,SPL 是怎么實現(xiàn)autoload_func 指針指向不同的函數(shù)呢庸汗?
原來,在SPL內(nèi)部定義了 一個函數(shù) spl_autoload_call() 和 一個全局變量autoload_functions手报。autoload_functions本質(zhì)上是一個HashTable蚯舱,不過我們可以將其簡單的看作一個鏈表,鏈表中的每一個元素都是一個函數(shù)指針,指向一個具有自動加載類功能的函數(shù)掩蛤。
spl_autoload_call()的作用就是按順序遍歷 autoload_functions枉昏,使得autoload_func指向每個自動加載函數(shù),如果加載成功就停止揍鸟,如果不成功就繼續(xù)遍歷下個自動加載函數(shù)兄裂,直到加載成功或者遍歷完所有的函數(shù)。
那么阳藻,autoload_functions 這個列表是誰來維護的呢晰奖?就是 spl_autoload_register() 這個函數(shù)。我們說的自動加載函數(shù)的注冊稚配,其實就是通過spl_autoload_register()把自動加載函數(shù)加入到 autoload_functions 列表畅涂。

原文鏈接:https://www.php.cn/php-ask-429829.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市道川,隨后出現(xiàn)的幾起案子午衰,更是在濱河造成了極大的恐慌,老刑警劉巖冒萄,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件臊岸,死亡現(xiàn)場離奇詭異,居然都是意外死亡尊流,警方通過查閱死者的電腦和手機帅戒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來崖技,“玉大人逻住,你說我怎么就攤上這事∮祝” “怎么了瞎访?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吁恍。 經(jīng)常有香客問我扒秸,道長播演,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任伴奥,我火速辦了婚禮写烤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拾徙。我一直安慰自己洲炊,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布锣吼。 她就那樣靜靜地躺著选浑,像睡著了一般蓝厌。 火紅的嫁衣襯著肌膚如雪玄叠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天拓提,我揣著相機與錄音读恃,去河邊找鬼。 笑死代态,一個胖子當(dāng)著我的面吹牛寺惫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蹦疑,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼西雀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了歉摧?” 一聲冷哼從身側(cè)響起艇肴,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎叁温,沒想到半個月后再悼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡膝但,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年冲九,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跟束。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡莺奸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出冀宴,到底是詐尸還是另有隱情灭贷,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布花鹅,位于F島的核電站氧腰,受9級特大地震影響枫浙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜古拴,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一箩帚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧黄痪,春花似錦紧帕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至挺尾,卻和暖如春鹅搪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背遭铺。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工丽柿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人魂挂。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓甫题,卻偏偏與公主長得像,于是被迫代替她去往敵國和親涂召。 傳聞我的和親對象是個殘疾皇子坠非,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353