Yii2 Day 9: 依赖注入实践

目标

Yii1.x经常被批评为强耦合,很难使用第三方库。通常持这样的观点的人会提及Yii1对DI的支持不够,或者说几乎没有。其实个人认为还是有一些朴素的支持的,比如application就是一个DI,各种组件都是通过 Yii::app()->xxx 的方式创建并引用的,怎么能说没有DI呢?至少实现了一些基本要素:

  1. 依赖的创建交给了application,而不需要程序员手动在代码中 new来
  2. 维护了一个依赖列表,同一个依赖,在多次被使用的时候,只需要创建一次

作为富有进取心的框架,Yii2肯定不能再继续受这样的批评啦,于是在DI上做了很多工作,达到了DI的几个基本要求

  1. 创建过程自动化,也就是Ioc,控制反转,即不需要程序员手动new
  2. 依赖的依赖管理,即当依赖又依赖于其他依赖时,能够自动创建其他依赖

关于Yii2的依赖注入实现与原理,有网友已经给出了详细的分析,推荐大家看看。地址:http://www.digpage.com/di.html,写得相当好啦,很赞。

实际例子

既然依赖注入据说有利于降低各个模块之间的耦合度,那么就让我们试试效果。架设我们的Store模块需要一个AdminContext的依赖,那么我们可以在模块的init方法中将依赖加进去:


//文件 StoreModule.php
 public function init()
{
    parent::init();

    //开始添加依赖
    $this->set('ac',[
       'class'=>'mtBridge\services\AdminContext',
    ]);
}

上面的代码,因为Module本身是继承自ServiceLocator,所以可以直接使用set方法添加一个依赖项。再看看AdminContext类的定义:


class AdminContext implements IAdminContext
{
    public $env;
    public $cs;

    public function __construct(EnvContext $e,CacheService $c)
    {
        $this->env = $e;
        $this->cs = $c;
    }
    public function doCallTest()
    {
        $siteName  = $this->env->getSiteName();
        $s = $this->cs->getCacheKey(1,'site');
        return array($siteName,$s);
    }
}

发现AdminContext的构造函数需要EnvContext和CacheService两个类型的对象作为参数,正好测试Yii2的DI的依赖的子依赖的支持。加个测试页面吧。


class TestController extends \yii\web\Controller
{
    public function actionIndex()
    {
        list($siteName,$key) = $this->module->get('ac')->doCallTest();
        list($siteName2,$key2) = $this->module->get('ac')->doCallTest();
        echo $siteName . '--key--' . $key;
    }
}

运行这个action的代码,正常输出,并且两次调用,ac也就实例化一次。

你可能感兴趣的:(yii2,DI,依赖注入)