源码分析自动加载系统会调用Loader::register()方法注册自动加载,这一步完成后,所有满足的类库specification(包括Composer依赖于加载第三方库)会被自动加载。系统自动加载由以下主要部分组成:1、注册系统自动加载方法\think\Loader::autoload2。注册系统命名空间的定义3.加载类库映射文件(如果存在)4.如果有Composer安装,则注册**Composer**自动加载5.注册extend扩展目录自动加载检测顺序一个类库是:1.是否定义了类库映射;2、PSR-4自动加载检测;3、PSR-0自动加载检测;4、可见定义类库映射的方式效率最高。源码/***注册自动加载机制*@accesspublic*@paramcallable$autoload自动加载处理方法*@returnvoid*/publicstaticfunctionregister($autoload=null){//注册系统自动加载spl_autoload_register($autoload?:'think\\Loader::autoload',true,true);//Composer自动加载支持“作曲家”。DS。'autoload_static.php';$declaredClass=get_declared_classes();$composerClass=array_pop($declaredClass);foreach(['prefixLengthsPsr4','prefixDirsPsr4','fallbackDirsPsr4','prefixesPsr0','fallbackDirsPsr0','classMap','files']as$attr){if(property_exists($composerClass,$attr)){self::${$attr}=$composerClass::${$attr};}}}else{self::registerComposerLoader();}}//注册命名空间定义self::addNamespace(['think'=>LIB_PATH.'think'.DS,'behavior'=>LIB_PATH.'behavior'.DS,'traits'=>LIB_PATH.'traits'.DS,]);//加载类库映射文件}self::loadComposerAutoloadFiles();//自动加载扩展目录self::$fallbackDirsPsr4[]=rtrim(EXTEND_PATH,DS);}Frameworkautoload/***autoload*@accesspublic*@paramstring$class类名*@returnbool*/publicstaticfunctionautoload($class){//检测命名空间别名if(!empty(self::$namespaceAlias)){$namespace=目录名($class);如果(isset(self::$namespaceAlias[$namespace])){$original=self::$namespaceAlias[$namespace].'\\'.basename($class);如果(class_exists($original)){返回class_alias($original,$class,false);}}}if($file=self::findFile($class)){//非Win环境不严格区分大小写if(!IS_WIN||pathinfo($file,PATHINFO_FILENAME)==pathinfo(realpath($文件),PATHINFO_FILENAME)){__include_file($file);返回真;}}返回假;}Detectnamespacealias检查是否添加了命名空间别名,通过别名找到原来的命名空间,如://Original\App\Http\Controller\Index::class//添加别名后,\Controller\Index::classthinkphp通过thinkLoader::addNamespaceAlias($namespace,$original)添加命名空间别名。//位置在thinkphp/library/think/Loader.php/***注册命名空间别名*@accesspublic*@paramarray|string$namespacenamespace*@paramstring$originalsourcefile*@returnvoid*/publicstaticfunctionaddNamespaceAlias($namespace,$original=''){if(is_array($namespace)){self::$namespaceAlias=array_merge(self::$namespaceAlias,$namespace);}else{self::$namespaceAlias[$namespace]=$original;}}注册thinkLoader::$namespaceAlias的属性,key为别名,value为原命名空间的数组。通过classmap、psr-4、psr-0查找文件/***查找文件*@accessprivate*@paramstring$class类名*@returnbool|string*/privatestaticfunctionfindFile($class){//class库映射if(!empty(self::$classMap[$class])){returnself::$classMap[$class];}//找到PSR-4$logicalPathPsr4=strtr($class,'\\',DS).分机;$first=$class[0];if(isset(self::$prefixLengthsPsr4[$first])){foreach(self::$prefixLengthsPsr4[$first]as$prefix=>$length){if(0===strpos($class,$prefix)){foreach(self::$prefixDirsPsr4[$prefix]as$dir){if(is_file($file=$dir.DS.substr($logicalPathPsr4,$length))){return$file;}}}}}//查找PSR-4后备目录foreach(self::$fallbackDirsPsr4as$dir){如果(is_file($file=$dir.DS.$logicalPathPsr4)){返回$file;}}//查找PSR-0if(false!==$pos=strrpos($class,'\\')){//命名空间类名$logicalPathPsr0=substr($logicalPathPsr4,0,$pos+1).strtr(substr($logicalPathPsr4,$pos+1),'_',DS);}else{//类似PEAR的类名$logicalPathPsr0=strtr($class,'_',DS).分机;}if(isset(self::$prefixesPsr0[$first])){foreach(self::$prefixesPsr0[$first]as$prefix=>$dirs){if(0===strpos($class,$prefix)){foreach($dirsas$dir){if(is_file($file=$dir.DS.$logicalPathPsr0)){返回$file;}}}}}//查找PSR-0fallbackdirsforeach(self::$fallbackDirsPsr0as$dir){if(is_file($file=$dir.DS.$logicalPathPsr0)){返回$file;}}//如果未找到,则将地图设置为false并返回returnself::$classMap[$class]=false;}thinkphp添加的自动加载是通过psr-4和classmap加载的,分别是:thinkLoader::addClassMap($class,$map='')和thinkLoader::addNamespace($namespace,$path='')的加载方式psr-4的方法是通过命名空间的首字母找到对应的命名空间,然后通过对应的命名空间拼接对应的文件目录,判断文件是否存在。如果存在,则加载该文件,实现类自动加载。classmap的加载方式是通过composerdu生成对应的classmap,直接搜索class对应的文件实现自动加载。其他需要深入理解的加载方式可以自行研究代码。/***注册自动加载机制*@accesspublic*@paramcallable$autoload自动加载处理方法*@returnvoid*/publicstaticfunctionregister($autoload=null){....//注册命名空间定义self::addNamespace(['think'=>LIB_PATH.'think'.DS,'behavior'=>LIB_PATH.'behavior'.DS,'traits'=>LIB_PATH.'traits'.DS,]);//加载类库映射文件}....}composerautoloadingcomposerautoloadinginthinkphp不是通过composer自带的autoload.php自动加载的。通过加载对应的psr文件来注册加载。/***注册自动加载机制*@accesspublic*@paramcallable$autoload自动加载处理方法*@returnvoid*/publicstaticfunctionregister($autoload=null){....//Composer自动加载支持if(is_dir(VENDOR_PATH.'composer')){if(PHP_VERSION_ID>=50600&&is_file(VENDOR_PATH.'composer'.DS.'autoload_static.php')){需要VENDOR_PATH.“作曲家”。DS。'autoload_static.php';$declaredClass=get_declared_classes();$composerClass=array_pop($declaredClass);foreach(['prefixLengthsPsr4','prefixDirsPsr4','fallbackDirsPsr4','prefixesPsr0','fallbackDirsPsr0','classMap','files']asattr){if(property_exists($composerClass,$attr)){self::${$attr}=$composerClass::${$attr};}}}else{self::registerComposerLoader();}}....}
