Symfony2.8 原始碼分析之類的載入

Yi_Zhi_Yu發表於2016-07-18

今天來寫寫Symfony2.8 這個框架的類載入機制

版本

Symfony 2.8

原理

在專案啟動時,Symfony 通過spl_autoload_register 註冊了要使用的類的自動載入處理方法, 在類第一次被使用的時候, 類檔案通過該方法被引入, 然後類才得以使用

原始碼分析

1.在symfony的入口檔案, 我們找到

#web/app_dev.php or web/app.php
$loader = require __DIR__.`/../app/autoload.php`

2.我們隨著這個路徑,我們找打了這個autoload.php, 主要內容如下:

# app/autoload.php
$loader = require __DIR__.`/../vendor/autoload.php`;
AnnotationRegistry::registerLoader(array($loader, `loadClass`));
return $loader;

其中

$loader = require __DIR__.`/../vendor/autoload.php`;

是為了註冊symfony的核心類的自動載入方法

AnnotationRegistry::registerLoader(array($loader, `loadClass`));

這個應該是為了使用者配置自定義的類的自動載入配置,暫時不看

3.我們再根據$loader 找到對應的autoload.php

# vendor/autoload.php
require_once __DIR__ . `/composer` . `/autoload_real.php`;
return ComposerAutoloaderInit447e0408cbcbbdf0d6df9a85eb1d2ead::getLoader();

這裡的getLoader()函式就是在autoload_real.php定義的,我們繼續深入這個檔案

4.找到autoload_real.php

# vendor/composer/autoload_real.php

我們找打getLoader 函式, 在這裡, 我加入了一些代註釋, 方便理解

public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }

        //這裡註冊的自動載入處理函式僅僅是為了能載入 ComposerAutoloadClassLoader
    spl_autoload_register(array(`ComposerAutoloaderInit447e0408cbcbbdf0d6df9a85eb1d2ead`, `loadClassLoader`), true, true);
        self::$loader = $loader = new ComposerAutoloadClassLoader();
        //$loader 才是實際的要載入的自動載入處理類
//得到自動載入處理類後ComposerAutoloadClassLoader就不需要了
spl_autoload_unregister(array(`ComposerAutoloaderInit447e0408cbcbbdf0d6df9a85eb1d2ead`, `loadClassLoader`));

        //以下是註冊 名稱空間與名稱空間下的類檔案的目錄的對映關係
        //或者註冊類名與類檔案的路徑的對映關係
        $map = require __DIR__ . `/autoload_namespaces.php`;
        foreach ($map as $namespace => $path) {
            $loader->set($namespace, $path);
        }

        //這裡也是
        $map = require __DIR__ . `/autoload_psr4.php`;
        foreach ($map as $namespace => $path) {
            $loader->setPsr4($namespace, $path);
        }

        //這裡也是
        $classMap = require __DIR__ . `/autoload_classmap.php`;
        if ($classMap) {
            $loader->addClassMap($classMap);
        }

        //該函式真正執行了`spl_autoload_register`
        $loader->register(true);

        //處理composer 的類載入
        $includeFiles = require __DIR__ . `/autoload_files.php`;
        foreach ($includeFiles as $fileIdentifier => $file) {
            composerRequire447e0408cbcbbdf0d6df9a85eb1d2ead($fileIdentifier, $file);
        }

        return $loader;
    }

開啟autoload_namespaces.php,autoload_psr4.php,autoload_classmap.php, 我們可以看到的是其中儲存的是名稱空間與名稱空間下的類檔案儲存的目錄的對映關係,或者是類名稱與類檔案路徑的對映關係

實際上, 這種對映關係為後面的類檔案定位提供直接的查詢幫助,ClassLoader 註冊(記錄)了這種對映關係, 再將其loadClass 註冊為自動載入處理函式(執行$loader->register(true);時), 最後,我們再使用到類的時候, 根據類名或者類的名稱空間,到已經註冊了的對映關係可以直接定位到類檔案, 將其include 我們就實現了所謂的自動載入

總結

以上就是Symfony2.8 的核心類的自動載入的處理

這是第一次寫框架原始碼分析, 比較粗糙, 如果各位有疑問, 請及時指出

另外, 這個分析只能作為大家研究symfony原始碼的參考,一定要對著原始碼一塊看才能理解,切忌僅僅通過直接閱讀本文就能理解

相關文章