资讯专栏INFORMATION COLUMN

Laravel源码阅读(前奏-反射实例化对象)

kuangcaibao / 1356人阅读

摘要:说明的核心容器有一部分就是利用反射来实现依赖注入时类的实例化。这是一个简化版示例。

说明
Laravel的核心容器,有一部分就是利用反射来实现依赖注入时类的实例化。这是一个简化版示例。
代码 测试用的类
/**
 * 坦克标准: 必须能开火
 */
interface Tank
{
    public function fire();
}


/**
 * 59坦克,使用100毫米炮
 */
class Tank59 implements Tank
{
    private $gun = 100;

    public function fire()
    {
        echo $this->gun . PHP_EOL;
    }
}

/**
 * 59加强版,可以使用100毫米炮或120毫米炮,默认120毫米炮
 */
class Tank59Plus implements Tank
{
    private $gun;

    public function __construct($gun = 120)
    {
        if($gun != 100 && $gun != 120) {
            throw new Exception("口径不合适");
        }

        $this->gun = $gun;
    }

    public function fire()
    {
        echo $this->gun . PHP_EOL;
    }
}

/**
 * 59超级版,可以使用任意口径的炮,必须提供一门火炮
 */
class Tank59Super implements Tank
{
    private $gun;

    public function __construct($gun)
    {
        $this->gun = $gun;
    }

    public function fire()
    {
        echo $this->gun . PHP_EOL;
    }
}

/**
 * 坦克营,装备59和59加强版,必须提供59和59加强版
 */
class TankArmy implements Tank
{
    private $tank59;
    private $tank59Plus;

    public function __construct(Tank59 $tank59, Tank59Plus $tank59Plus)
    {
        $this->tank59 = $tank59;
        $this->tank59Plus = $tank59Plus;
    }

    public function fire()
    {
        echo $this->tank59->fire();
        echo $this->tank59Plus->fire();
    }
}
容器
/**
 * 兵工厂
 */
class Factory
{
    /**
     * 创建实体对象
     */
    public static function build($blueprint)
    {
        //反射,获取类细节
        $reflector = new ReflectionClass($blueprint);

        //无法创建的类,比如接口,抽象类
        if(!$reflector->isInstantiable()) {
            throw new Exception("提供的不是坦克图纸,不能制造");
        }

        //获取类的构造方法
        $constructor = $reflector->getConstructor();
        if (is_null($constructor)) {
            //没有构造方法,直接new
            return new $blueprint;
        }

        $parameters = [];
        //获取构造方法依赖的参数
        $dependencies = $constructor->getParameters();
        foreach ($dependencies as $dependency) {
     
            if(is_null($dependency->getClass())) {
                //依赖参数不是对象
                //如果构造方法参数有默认值,获取默认值
                if($dependency->isDefaultValueAvailable()) {
                    $parameters[] = $dependency->getDefaultValue();
                }
            }
            else {
                //依赖参数是对象,递归创建
                $parameters[] = self::build($dependency->getClass()->name);
            }
        }

        if(!$parameters) {
            //有构造方法且构造方法有参数,却没有可以提供的实参,无法创建
            throw new Exception("坦克缺少必要的零件,不能制造");
        }
        else {
            //使用反射提供的方法创建对象,传入参数
            return  $reflector->newInstanceArgs($parameters);
        }
    }
}
测试 Tank
$tank = Factory::build(Tank::class);
echo $tank->fire();

//输出
//PHP Fatal error:  Uncaught Exception: 提供的不是坦克图纸,不能制造 
Tank59
$tank = Factory::build(Tank59::class);
echo $tank->fire();

//输出
//100
Tank59Plus
$tank = Factory::build(Tank59Plus::class);
echo $tank->fire();

//输出
//120
Tank59Super
$tank = Factory::build(Tank59Super::class);
echo $tank->fire();

//输出
//Fatal error: Uncaught Exception: 坦克缺少必要的零件,不能制造
TankArmy
$tank = Factory::build(TankArmy::class);
echo $tank->fire();

//输出
//100
//120 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/28627.html

相关文章

  • Laravel源码解析之反射的使用

    摘要:本章讲解反射类的使用及对反射的使用。各位很清楚,方法用于解析类,所有方法的实现一定是在引用的文件内。致谢感谢你看到这里,本篇文章源码解析靠个人理解。 showImg(https://segmentfault.com/img/bVbhjvY?w=600&h=296); 前言 PHP的反射类与实例化对象作用相反,实例化是调用封装类中的方法、成员,而反射类则是拆封类中的所有方法、成员变量,并...

    pinecone 评论0 收藏0
  • Laravel深入学习2 - 控制反转容器

    摘要:控制反转容器控制反转使依赖注入变得更加便捷。有瑕疵控制反转容器是实现的控制翻转容器的一种替代方案。容器的独立使用即使没有使用框架,我们仍然可以在项目中使用安装组件来使用的控制反转容器。在没有给定任何信息的情况下,容器是无法实例化相关依赖的。 声明:本文并非博主原创,而是来自对《Laravel 4 From Apprentice to Artisan》阅读的翻译和理解,当然也不是原汁原味...

    worldligang 评论0 收藏0
  • LaravelLaravel 框架关键技术解析·读书笔记(一)

    摘要:判断是否存在构造函数,不存在直接实例化,存在则通过来获取输入函数,并有相应的方法解决依赖参数问题,实现依赖注入。 Laravel 框架关键技术解析·读书笔记(一) 第一章 入口文件 请求访问的入口文件,主要完成几部分工作,分别是: 自动加载函数的添加 服务器实例化与服务注册 路由加载 请求实例化与路由分发 相应生成与发送 其中,自动加载函数用于包含引用文件,改文件是composer...

    CocoaChina 评论0 收藏0
  • Laravel 依赖注入源码解析

    在 Laravel 的控制器的构造方法或者成员方法,都可以通过类型约束的方式使用依赖注入,如: public function store(Request $request) { //TODO } 这里 $request 参数就使用了类型约束,Request 是类型约束的类型,它是一个类:IlluminateHttpRequest. 本文研究 Laravel 的依赖注入原理,为什么这样定义...

    Donne 评论0 收藏0
  • 反射在 PHP 中的应用

    摘要:反射在每个面向对象的编程语言中都存在,它的主要目的就是在运行时分析类或者对象的状态,导出或提取出关于类方法属性参数等的详细信息,包括注释。反射是操纵面向对象范型中元模型的,可用于构建复杂,可扩展的应用。 反射在每个面向对象的编程语言中都存在,它的主要目的就是在运行时分析类或者对象的状态,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。 反射是操纵面向对象范型中元模型的 AP...

    stormgens 评论0 收藏0

发表评论

0条评论

kuangcaibao

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<