yiya 2018-01-25 14:42:58 3820次浏览 1条评论 0 1 0

第一次发帖,写的不好还请各位多多包涵。废话不多说,开始。

官方文档中对依赖注入容器有讲解,但是介绍的比较简略,这里对其进行一些详细的讲解,我们这里单独讨论构造方法注入,想必若是把构造方法注入理解了,yii的依赖注入容器也就不难明白了。
官方文档中相关内容地址:http://www.yiiframework.com/doc-2.0/guide-concept-di-container.html

为什么要使用依赖注入容器?

有这样一种情况,当我们使用一个类的时候,这个类又调用了别的类,如:

class A{

}
class B
{
    public function __construct(A $a)
    {
    }
}

如上面这种情况,我们若想要使用类B,一般是这样写的:

$a=new A;
$b=new B($a);

若是依赖关系再复杂一些,依赖链再长一些,如D依赖C和B,B又依赖A,我们需要这样来使用D:

$a=new A;
$b=new B($a);
$c=new C;
$d=new D($c,$b);

其实上面的例子还不算复杂,在项目中依赖的关系往往会比这个还要复杂,若是我们都像上面这样写的话,一来麻烦,二来容易出错,我们有了依赖注入容器以后,想要使用类D,一行代码就可以了
$d=$container->get('D');

下面我们来讨论以下依赖注入容器构造方法注入是如何实现的吧,为了让我们理解起来更加简单,我们一步一步来实现构造注入容器。

1、我们先做一个类,这个类先不实现依赖注入,只是简单的实现给一个类,然后返回这个类的实例,我们会这样写:

class Container
{
    public function get($class){
        $reflection= new ReflectionClass($class);
        return $reflection->newInstanceArgs();
    }
}

若是我们要使用类的构造函数没有参数,我们这样写是没有问题的,但若是构造函数有参数,我们就必须使用ReflectionClass的相关方法获取到类的构造函数的参数信息,所以第二步:

2、

class Container
{
    public function get($class){
        list($reflection,$dependencies)=getDependencies($class);
        return $reflection->newInstanceArgs($dependencies);
    }
    public function getDependencies($class){
        $reflection= new ReflectionClass($class);
        $constructor = $reflection->getConstructor();
        $dependencies = [];
        if($constructor!=null){
            foreach($constructor->getParameters() as $param){
                if ($param->isDefaultValueAvailable()) {
                    $dependencies[] = $param->getDefaultValue();
                } else {
                    $c=$param->getClass();
                    $dependencies[]=Instance::of($c==null?null:$c->getName());
                }
            }
        }
        return [$reflection,$dependencies];
    }
}

上面的添加了一个方法getDependencies用来获取类的构造函数的相关信息

觉得很赞
您需要登录后才可以评论。登录 | 立即注册