ThinkPHP容器源码深度解析(4)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: ThinkPHP容器源码深度解析

反射之战优化代码


最终优化完成的代码就是这样的,接下来对这段代码进行简单的解析。


  • 在之前代码的基础上只修改了kaka/container/Container.php这个类里边的get方法
  • 判断这个名person是否在容器中
  • 使用反射接口,然后获取传进去person类的构造方法
  • 如果person没有构造方法就直接返回person这个实例即可
  • 如存person在构造函数,则获取person构造函数的方法
  • 由于person类里边的构造函数的参数不会仅限于一个
  • 所以需要循环来获取每个参数的对象
  • 最后使用反射的 newInstanceArgs接口创建对应的实例
<?php
/**
 * Created by PhpStorm.
 * User: 咔咔
 * Date: 2020/9/21
 * Time: 19:04
 */
namespace container;
class Container
{
    /**
     * 存放容器
     * @var array
     */
    public $instances = [];
    /**
     * 容器的对象实例
     * @var array
     */
    protected static $instance;
    /**
     * 定义一个私有的构造函数防止外部类实例化
     * Container constructor.
     */
    private function __construct() {
    }
    /**
     * 获取当前容器的实例(单例模式)
     * @return array|Container
     */
    public static function getInstance ()
    {
        if(is_null(self::$instance)){
            self::$instance = new self();
        }
        return self::$instance;
    }
    public function set ($key,$value)
    {
        return $this->instances[$key] = $value;
    }
    /**
     * User : 咔咔
     * Notes: 获取容器里边的实例  使用反射
     * Time :2020/9/21 22:04
     * @param $key
     * @return mixed
     */
    public function get ($key)
    {
        if(!empty($this->instances[$key])){
            $key = $this->instances[$key];
        }
        $reflect = new \ReflectionClass($key);
        // 获取类的构造函数
        $c = $reflect->getConstructor();
        if(!$c){
            return new $key;
        }
        // 获取构造函数的参数
        $params = $c->getParameters();
        foreach ($params as $param) {
         /**
             ReflectionClass Object
            (
                [name] => container\dependency\Car
            )
             */
            $class = $param->getClass();
            if(!$class){
            }else{
                // container\dependency\Car
                $args[] = $this->get($class->name);
            }
        }
        // 从给出的参数创建一个新的类实例
        return $reflect->newInstanceArgs($args);
    }
}

image.png


文件application/index/controller/Container.php这里就是修改之后的变动


image.png


问题一:kaka/container/dependency/Person.php里边的参数Car是什么意思


这个问题其实很简单,你可以看到这个Car就是同目录的Car.php文件。你就可以直接理解为同命名空间下的文件。


image.png


问题二:文件application/index/controller/Container.php为什么可以直接调用buy方法


首先看一下obj的值,返回的这个对象里边就已经把Car的类实例化好了,所以无需在实例化,可直接调用buy方法,因为参数会直接传递过去


image.png

image.png



以上就是咔咔实现的一个简单的容器,如有不明白或者问题可以直接评论区回复即可。


接下来就是针对框架里边的容器进行剖析,一步一步的追溯到根源。


六、Container容器类剖析之Countable巧用

关于Countable这块内容一直没想好是否是文章的形式写出展现给大家,但是在后期阅读源码时大量的出现了Countable的应用。


为了大家能看懂每一个技术点,咔咔还是写了出来。


在文件thinkphp/library/think/Container.php中,就可以直接看到使用了Countable接口,并且实现了它!


image.png


来到Countable这接口中,我们只能看到一个方法就是count().


根据代码中Count elements of an object这行注释可以了解到,这个接口是计算对象的元素


image.png


根据PHP文档的说明在深入了解一下。


文档说明当你执行count()方法时就相当于在执行上边的abstract public Countable::count ( void ) : int抽象方法。


image.png



相关文章
|
3天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
14 2
|
3天前
|
存储 安全 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代码示例进行实战演示。
36 3
|
24天前
|
缓存 前端开发 JavaScript
前端的全栈之路Meteor篇(二):容器化开发环境下的meteor工程架构解析
本文详细介绍了使用Docker创建Meteor项目的准备工作与步骤,解析了容器化Meteor项目的目录结构,包括工程准备、环境配置、容器启动及项目架构分析。提供了最佳实践建议,适合初学者参考学习。项目代码已托管至GitCode,方便读者实践与交流。
|
28天前
|
存储 应用服务中间件 云计算
深入解析:云计算中的容器化技术——Docker实战指南
【10月更文挑战第14天】深入解析:云计算中的容器化技术——Docker实战指南
52 1
|
1月前
|
存储
让星星⭐月亮告诉你,HashMap的put方法源码解析及其中两种会触发扩容的场景(足够详尽,有问题欢迎指正~)
`HashMap`的`put`方法通过调用`putVal`实现,主要涉及两个场景下的扩容操作:1. 初始化时,链表数组的初始容量设为16,阈值设为12;2. 当存储的元素个数超过阈值时,链表数组的容量和阈值均翻倍。`putVal`方法处理键值对的插入,包括链表和红黑树的转换,确保高效的数据存取。
53 5
|
30天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
65 0
|
1月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
66 0
|
1月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
52 0
|
1月前
|
存储 Java C++
Collection-PriorityQueue源码解析
Collection-PriorityQueue源码解析
59 0

推荐镜像

更多