Blogger Information
Blog 81
fans 1
comment 0
visits 123889
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
tp中的app()助手函数是如何获取对象的?
有什么是忘不了的的博客
Original
1445 people have browsed it

tp给我们提供啦一个容器的概念,用来储存我们生产的类实例。在下次需要使用类实例时可以快速获取。

那app()助手函数是如何工作的:    

    通过查看助手文件得到他其实调用的是:Container::get()方法。

    function app($name = 'think\App', $args = [], $newInstance = false)
    {
        return Container::get($name, $args, $newInstance);
    }

    我们在去看Container::get()方法。

    public static function get($abstract, $vars = [], $newInstance = false)
    {
        //通过getInstance方法创建一个当前容器的实例(单例模式)再去调用make()方法
        return static::getInstance()->make($abstract, $vars, $newInstance);
    }

    我们来看make()方法:这个方法很重要,门面其实也是通过这个方法来创建对象。

    public function make($abstract, $vars = [], $newInstance = false)
    {
        if (true === $vars) {
            // 总是创建新的实例化对象
            $newInstance = true;
            $vars        = [];
        }
        static $i = 0;
        $abstract = isset($this->name[$abstract]) ? $this->name[$abstract] : $abstract;
        //通过容器获取类的对象
        if (isset($this->instances[$abstract]) && !$newInstance) {
//            echo '容器中'.$i++.'<br>';
            return $this->instances[$abstract];
        }
            //通过反射创建类的对象
        if (isset($this->bind[$abstract])) {
            $concrete = $this->bind[$abstract];
            if ($concrete instanceof Closure) {
                $object = $this->invokeFunction($concrete, $vars);
                echo '反射'.$i++.PHP_EOL;
            } else {
                $this->name[$abstract] = $concrete;
                return $this->make($concrete, $vars, $newInstance);
            }
        } else {
            echo '反射'.$i++.PHP_EOL;
            $object = $this->invokeClass($abstract, $vars);
        }

        if (!$newInstance) {
            $this->instances[$abstract] = $object;
        }

        return $object;
    }

我为了证明app()在调用的时候是通过容器来获取对象的还是通过反射来获取对象的,在这个类中定义了一个:static $i = 0;和echo '反射'.$i++.PHP_EOL;来输出调用的方法和次数。方便观察。

当我的方法为空时:

(TPBSPE)VGJ`MBK4ZH[IGL9.png

输出为:

W8({%TRHB`02[UC@WN0TT$C.png

为什么会使出  17次的放射呢?

因为在框架初始化的时候会来获取一些默认的类对象(大概是这个意思)。所以这前17次输出都和我们没有关系

现在我在方法里调用一次我自己定义的一个类文件。

J6GWX4O3}X$O7W3HYK2ZIL3.png

再看输出

50T]]L@V{OB5V_25(%IS)EG.png

这是输出多啦一次 ‘反射’这说明当我们通过app()来获取一个我们未向容器注册过的类的时候,他会通过我们提供的命名空间,用反射来创建这个类的对象。

当我们调用两次app()来获取相同的类对象时:

    public function lize(){
//        bind('Redis',new \Redis);
        $redis = app('Redis');
        $redis = app('Redis');
    }

再看输出:

50T]]L@V{OB5V_25(%IS)EG.png并没有多输出一次‘反射’,这说明我们第二次调用的时候并没有通过反射来获取类对象。而是做的容器。

总结:

    当我们通过app()来获取一个类对象时,先会在容器里获取,获取不到去通过反射来获取。反射获取对象成功后,在吧这个对象放到容器里。下次获取的时候直接去容器里获取。(去不去容器里获取还可以通过,app()的第二个参数来决定,当为true时就不会走容器,不管容器里有没有。)








Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post