依赖注入,ioc容器,php反射

IoC

ioC 容器,也可以称为服务容器,这个是laravel框架的核心思想,就是说,把东西整合在一个容器中,需要什么就取什么的意思,一个容器,一定要有两个方法,一个是取,一个是存。

这一个就是ioc容器,简单的代码介绍

<?php

class IoC
{
    protected static $registry = [];

    public static function bind($name, callable $resolver) //传入类名和类对象实例
    {
        static::$registry[$name] = $resolver;
    }

    public static function make($name) //静态工厂方法
    {
        if (isset(static::$registry[$name])) {
            $resolver = static::$registry[$name];
            return $resolver(); //实例化
        }
        throw new Exception('Alias does not exist in the IoC registry.');// 容器中没有你想要的对象
    }
}

class a
{
    public function xx()
    {
        echo 123;
    }
}

IoC::bind('a', function () {
    return new a();
});
$a = IoC::make('a');
$a->xx();

 

php反射

ReflectionClass() 也就是这个类,这个类,他里面封装类很多方法,通过这里面的方法,你可以反射出 另一个类的参数,构造方法,形参,受保护的变量等等,甚至连注释都能反射获取到

 

 

依赖注入

所谓依赖,就是a class 依赖 b class   所谓注入,就是把 b class 放到a class 中,然后又把 b class 这个对象 存储在a class 中的一个受保护变量中,这就是依赖注入

看看下面这段代码就是依赖注入

<?php

class a
{
    protected $info;

    public function __construct(b $b)// 依赖b class
    {
        $this->info = $b;
    }

    public function a()
    {
        return $this->info->b();
    }

}

class  b
{
    public function __construct()
    {

    }

    public function b()
    {
        return 'class b funciton b';
    }

}

$b = new b();
$a = new a($b);
$c = $a->a();
var_dump($c);

 

ioc容器+php反射  实现依赖注入

<?php
// ioc-di容器 控制反转 依赖注入
// laravel 就是用了ioc这个思想,就是一个类方法,他需要依赖另外一个,是从ioc容器中拿的,而不是直接new的
// 容器就是存储了很多东西,需要的时候就用他的,不需要的时候就不用他
// 不需要在a类中直接newb类,而是让ioc容器将b给a,这就叫做控制反转,将程序内部转移到外部去管理
class peopel {
    public function hahah() {
        echo 2;
    }
}

class  phone
{
    public $obj;
    public $p;

    public function __construct(usb $obj, peopel $p)
    {
        $this->obj = $obj;//注意这里主动去new了需要的对象
        $this->p = $p;
    }

    public function act()
    {
        $this->obj->dosth();
        $this->p->hahah();
    }
}

class usb
{
    public function dosth()
    {
        echo 1;
    }
}

class container
{

    public $objs = [];//存储资源

    /***
     * 负责存储资源的方法
     * @param $class
     * @param $closure_obj
     */
    public function bind($class, $closure_obj)
    {
        if (!$closure_obj instanceof Closure) {// $closure_obj instanceof Closure 是不是一个闭包
            // 如果不是闭包的话就要把他变成闭包
            $this->objs[$class] = function () use ($closure_obj) {
                return $this->ref($closure_obj);
            };
        } else {
            // 是闭包的话就把他存储起来
            $this->objs[$class] = $closure_obj;
        }

    }

    /***
     * 获取存储的资源
     * @param $class
     * @return mixed
     */
    public function make($class)
    {
        if (isset($this->objs[$class])) {// 当前是不是存在存储资源里面
            $new = $this->objs[$class];// 在的话就返回
        } else {
            /**
                下面这步,最终是这样的:
                $container->bind('usb', function () {
                    return new usb;
                });
             */

            $new = function () use ($class) {
                return $this->ref($class);// 如果不在绑定关系里面的话,就要反射一下,而且要是一个闭包
            };
        }
        return $new();
    }

    /***
     * 返回一个实例化的对象,这里用到php反射  也就是这个 ReflectionClass
     * @param $class
     * @param array $params
     * @return mixed|object|null
     * @throws ReflectionException
     */
    public function ref($class, $params = [])
    {
        // ReflectionClass 这个是php的反射api
        $ref = new ReflectionClass($class);
        if ($ref->isInstantiable()) {// isInstantiable检查类是否可实例化
            $constructor = $ref->getConstructor();// 获取里面的构造方法 getConstructor
            if (!is_null($constructor)) {
                $pars = $constructor->getParameters();// 获取里面的参数getParameters,获取构造函数的依赖(形参),返回一组ReflectionParameter对象组成的数组表示每一个参数
                if (empty($pars)) {//如果不依赖于任何的类,就直接实例化当前的就行了
                    return new $class;
                } else {// 如果这个形参是存在的,就去获取形参的实例化对象
                    foreach ($pars as $par) {//如果形参有多个
                        $dependencyClass = $par->getClass();// 获得类型提示类。就比如这种  function(Par $par) 获取到的就是Par 这个是类的名称
                        if (is_null($dependencyClass)) {
                            $dependencies[] = NULL;
                        } else {
                            // 类存在创建类实例,make去获取已经存储好的实例,$dependencies这个就是已经实例化后的对象了
                            $dependencies[] = $this->make($par->getClass()->name);
                        }
                    }
                    return $ref->newInstanceArgs($dependencies);//newInstanceArgs从给出的参数创建一个新的类实例
                }
            } else {//如果没有构造方法就返回这个对象
                return new $class;
            }
        }
        return null;
    }
}

$container = new container;
//$container->bind('usb', function () {
//    return new usb;
//});
$container->bind('phone', 'phone');
$phone = $container->make('phone');
$phone->act();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值