zoukankan      html  css  js  c++  java
  • 深入 Laravel 内核之 PHP 反射机制和依赖注入

    结论:

    • PHP中提供了反射类来解析类的结构;
    • 通过反射类可以获取到类的构造函数及其参数和依赖;
    • 给构造函数的参数递归设置默认值后,即可使用这些带默认值的参数通过 newInstanceArgs 实例化出类对象;
    • 在实例化的过程中,依赖的类也会被实例化,从而实现了依赖注入。

    PHP中反射类的常用方法:

    // 通过类名 Circle 实例化反射类
    $reflectionClass = new reflectionClass(Circle::class);
    // 获取类常量
    $reflectionClass->getConstants();
    // 获取类属性
    $reflectionClass->getProperties();
    // 获取类方法
    $reflectionClass->getMethods();
    // 获取类的构造函数
    $constructor = $reflectionClass->getConstructor();
    // 获取方法的参数
    $parameters = $constructor->getParameters();
    // 通过参数默认值数组实例化类创建对象
    $class = $reflectionClass->newInstanceArgs($dependencies);
    

    创建两个具有依赖关系的类:

    class Point
    {
        public $x;
        public $y;
    
        public function __construct($x = 0, $y = 0)
        {
            $this->x = $x;
            $this->y = $y;
        }
    }
    
    class Circle
    {
        // 圆的半径
        public $radius;
    
        // 圆心位置
        public $center;
    
        const PI = 3.14;
    
        public function __construct(Point $point, $radius = 1)
        {
            $this->center = $point;
            $this->radius = $radius;
        }
    
        // 打印圆心位置的坐标
        public function printCenter()
        {
            printf('圆心的位置是:(%d, %d)', $this->center->x, $this->center->y);
        }
    
        //计算圆形的面积
        public function area()
        {
            return 3.14 * pow($this->radius, 2);
        }
    }
    

    创建两个方法:

    make 方法负责解析类和构建类的对象;

    getDependencies 负责依赖解析并初始化参数默认值;

    //构建类的对象
    function make($className)
    {
        try {
            $reflectionClass = new ReflectionClass($className);
            $constructor = $reflectionClass->getConstructor();
            $parameters  = $constructor->getParameters();
            $dependencies = getDependencies($parameters);
    
            // 用指定的参数创建一个新的类实例
            return $reflectionClass->newInstanceArgs($dependencies);
        } catch (ReflectionException $e) {
            throw new Exception("{$className} not found.");
        }
    }
    
    //依赖解析并初始化参数默认值
    function getDependencies($parameters)
    {
        $dependencies = [];
        // Circle 类的参数为 point 和 radius
        // Point 类的参数为 x 和 y
        foreach($parameters as $parameter) {
            $dependency = $parameter->getClass();
            // 如果参数不是类
            if (is_null($dependency)) {
                // 可选参数,有默认值
                if($parameter->isDefaultValueAvailable()) {
                    $dependencies[] = $parameter->getDefaultValue();
                }
                // 必传参数暂时先给一个默认值
                else {
                    $dependencies[] = '0';
                }
            }
            // 如果参数是类
            else {
                // 递归进行依赖解析
                $dependencies[] = make($parameter->getClass()->name);
            }
        }
    
        return $dependencies;
    }
    

    测试:

    // 实例化对象
    $circle = make('Circle');
    // 调用对象的方法
    $area = $circle->area();
    var_dump($circle, $area);
    

    过程说明:

    make('Circle')
    	getDependencies(Point, int)
    		make('Point')
    			getDependencies(int, int)
    			new Point(int, int);
    		return Point;
    	new Circle(Point, int);
    return Circle;
    
  • 相关阅读:
    Python 常用内置函数
    Java Graphics 2D绘制图片 在Liunx上乱码
    LInux Centos7 重装yum
    Spring Boot 异步调用
    Linux 清除N天前的 日期文件夹(yyyy-MM-dd)
    Python 2.75升级3.6.3
    Linux 移除python Error: Trying to remove “yum”, which is protected
    Java Future 使用场景
    CF446D DZY Loves Games
    三 lambda表达式有什么用
  • 原文地址:https://www.cnblogs.com/danhuang/p/13164345.html
Copyright © 2011-2022 走看看