tp5源码解析--自动加载类

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 在TP5的框架使用过程中,自动加载类是可能会接触到,上手不难,但若想随心所欲的用,还是需要了解一番。用了千次,却没看过一次源码,学习源码,起码对TP5这个框架使用更加得心应手,毕竟技术服务于业务,能够写出更简介、更方便、更有效的业务代码,本身就是一件身心愉悦的事儿;

在TP5的框架使用过程中,自动加载类是可能会接触到,上手不难,但若想随心所欲的用,还是需要了解一番。用了千次,却没看过一次源码,学习源码,起码对TP5这个框架使用更加得心应手,毕竟技术服务于业务,能够写出更简介、更方便、更有效的业务代码,本身就是一件身心愉悦的事儿;

自动加载流程

第一步,TP框架初始化

Loader会走如下逻辑;

加载autoload_static.php中的 prefixLengthsPsr4prefixDirsPsr4两个数组;

public static $prefixLengthsPsr4 = array (
        't' => 
        array (
            'think\\composer\\' => 15,
            'think\\' => 6,
        ),
        'a' => 
        array (
            'app\\' => 4,
        ),
    );
    public static $prefixDirsPsr4 = array (
        'think\\composer\\' => 
        array (
            0 => __DIR__ . '/..' . '/topthink/think-installer/src',
        ),
        'think\\' => 
        array (
            0 => __DIR__ . '/../..' . '/thinkphp/library/think',
        ),
        'app\\' => 
        array (
            0 => __DIR__ . '/../..' . '/application',
        ),
    );


再通过self::${$attr} = $composerClass::${$attr} 变成当前类的静态数组;

详细逻辑如下:

// Composer 自动加载支持
        if (is_dir(VENDOR_PATH . 'composer')) {
            if (PHP_VERSION_ID >= 50600 && is_file(VENDOR_PATH . 'composer' . DS . 'autoload_static.php')) {
      //引入'autoload_static.php;
                require VENDOR_PATH . 'composer' . DS . 'autoload_static.php';
        //获取全部对象
                $declaredClass = get_declared_classes();
        //弹出最后一个对象类 也就是autoload_static.php
                $composerClass = array_pop($declaredClass);
    //查看autoload_static.php对象数组
                foreach (['prefixLengthsPsr4', 'prefixDirsPsr4', 'fallbackDirsPsr4', 'prefixesPsr0', 'fallbackDirsPsr0', 'classMap', 'files'] as $attr) {
                    if (property_exists($composerClass, $attr)) {
          //转化成自己类的静态数组
                        self::${$attr} = $composerClass::${$attr};
                    }
                }
            } else {
      //加载Psr0方法
                self::registerComposerLoader();
            }
        }
        // 注册命名空间定义
        self::addNamespace([
            'think'    => LIB_PATH . 'think' . DS,
            'behavior' => LIB_PATH . 'behavior' . DS,
            'traits'   => LIB_PATH . 'traits' . DS
        ]);
        // 加载类库映射文件
        if (is_file(RUNTIME_PATH . 'classmap' . EXT)) {
            self::addClassMap(__include_file(RUNTIME_PATH . 'classmap' . EXT));
        }
        self::loadComposerAutoloadFiles();
        // 自动加载 extend 目录,可以在这里加相关目录,拓展包就是在这手动放入 extend中加载
        self::$fallbackDirsPsr4[] = rtrim(EXTEND_PATH, DS);

第二步 new class()

当一个class不存在走自动加载方法; spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true) 通过spl_autoload_register 走autoload($class)方法;

autoload($class)->检测命名空间别名->通过上一步初始化生成的静态化数组查找相关class文件是否存在->返回对像(结束);

public static function autoload($class)
    {
        // 检测命名空间别名
        if (!empty(self::$namespaceAlias)) {
            $namespace = dirname($class);
            if (isset(self::$namespaceAlias[$namespace])) {
                $original = self::$namespaceAlias[$namespace] . '\\' . basename($class);
                if (class_exists($original)) {
                    return class_alias($original, $class, false);
                }
            }
        }
//查看文件
        if ($file = self::findFile($class)) {
            // 非 Win 环境不严格区分大小写
            if (!IS_WIN || pathinfo($file, PATHINFO_FILENAME) == pathinfo(realpath($file), PATHINFO_FILENAME)) {
      //引入文件
                __include_file($file);
                return true;
            }
        }
        return false;
    }


其中核心方法

public static function register($autoload = null)
    {
     // 注册系统自动加载
        spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
  }


TP自动加载方法

composer自动方法

其实两个自动加载打通小异;

Tp在加载方法,个人认为是借鉴composer;

目录
相关文章
|
3天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
16 2
|
4天前
|
存储 安全 Linux
Golang的GMP调度模型与源码解析
【11月更文挑战第11天】GMP 调度模型是 Go 语言运行时系统的核心部分,用于高效管理和调度大量协程(goroutine)。它通过少量的操作系统线程(M)和逻辑处理器(P)来调度大量的轻量级协程(G),从而实现高性能的并发处理。GMP 模型通过本地队列和全局队列来减少锁竞争,提高调度效率。在 Go 源码中,`runtime.h` 文件定义了关键数据结构,`schedule()` 和 `findrunnable()` 函数实现了核心调度逻辑。通过深入研究 GMP 模型,可以更好地理解 Go 语言的并发机制。
|
16天前
|
消息中间件 缓存 安全
Future与FutureTask源码解析,接口阻塞问题及解决方案
【11月更文挑战第5天】在Java开发中,多线程编程是提高系统并发性能和资源利用率的重要手段。然而,多线程编程也带来了诸如线程安全、死锁、接口阻塞等一系列复杂问题。本文将深度剖析多线程优化技巧、Future与FutureTask的源码、接口阻塞问题及解决方案,并通过具体业务场景和Java代码示例进行实战演示。
37 3
|
24天前
|
存储 Java API
详细解析HashMap、TreeMap、LinkedHashMap等实现类,帮助您更好地理解和应用Java Map。
【10月更文挑战第19天】深入剖析Java Map:不仅是高效存储键值对的数据结构,更是展现设计艺术的典范。本文从基本概念、设计艺术和使用技巧三个方面,详细解析HashMap、TreeMap、LinkedHashMap等实现类,帮助您更好地理解和应用Java Map。
41 3
|
1月前
|
存储
让星星⭐月亮告诉你,HashMap的put方法源码解析及其中两种会触发扩容的场景(足够详尽,有问题欢迎指正~)
`HashMap`的`put`方法通过调用`putVal`实现,主要涉及两个场景下的扩容操作:1. 初始化时,链表数组的初始容量设为16,阈值设为12;2. 当存储的元素个数超过阈值时,链表数组的容量和阈值均翻倍。`putVal`方法处理键值对的插入,包括链表和红黑树的转换,确保高效的数据存取。
53 5
|
1月前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
110 5
|
1月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
67 0
|
1月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
52 0
|
1月前
|
存储 Java C++
Collection-PriorityQueue源码解析
Collection-PriorityQueue源码解析
60 0
|
1月前
|
安全 Java 程序员
Collection-Stack&Queue源码解析
Collection-Stack&Queue源码解析
80 0

推荐镜像

更多