依赖注入 IOC容器的实现

由于 我的框架(框架 请看上一篇)使用了两套数据源

一套是http的接口请求方式,一套是直接链接 mysql的方式

故而 两套方式,要是想通过配置化的方式就能够实现 数据源的切换,
进而想到了 依赖注入的方式实现该功能

 

最早接触 IOC容器 是由于之前做 .net的时候,那时候听别人讲这些专业名词  觉得挺高大上的,不过不知道它的优势在哪。

 

后面深入了解了之后,由于 注入的解耦的特性,以及 它的高扩展性  确实非常高深。

 

就像 我们目前做的一个系统,由于之前用的是mysql直接连的数据源,到现在 数据量庞大的时候,发现了它的数据读写瓶颈,可是也很无奈呀。

 

想要将数据源移植到 分布式的微服务架构中, 前端上只做一些简单的php处理。可是由于之前的代码扩展性很差,工程量 很庞大,只能开始重构系统了。

非常痛苦。

 

下面通过user 的 数据添加功能进行操作

 

依赖注入

 

构造注入 

通过构造方法进行对象注入

public class UserModels
{
    private Db $db;
    // 注入
    public function UserModels($server)
    {
        $this->db=$server;
    }
    
    public function add($data)
    {
        $this->db->add($data);
    }
}

public class UserController
{
    public addUser()
    {
        $user=array();
        Db mysql=new Mysql();
        
        UserModels usermodels=new UserModels(mysql);
        
        usermodels->add($user);
    }
}

 

属性注入
通过setter 方法进行对象注入

public class UserModels
{
    private Db $db;
    // 注入
    public function setDb($server)
    {
        $this->db=$server;
    }
    public function add($data)
    {
        $this->db->add($data);
    }
}

public class UserController
{
    public addUser()
    {
        $user=array();
        Db mysql=new Mysql();
        
        UserModels usermodels=new UserModels();
        usermodels->setDb(mysql);
        usermodels->add($user);
    }
}

 

 

属性注入的话,就是当你想要注入该对象就注入 不用在我们的对象构造的时候就注入其中,会耦合性更低。
否则,如果我们一个类 使用了多个对象,那岂不是 构造方法的参数 一堆堆的。。

 

接口注入

  接口注入的方式就是通过一个接口进行对象注入

public interface Models
{
    public function initDb($server);
}

public class UserModels implements Models
{
    private Db $db;
    // 注入
    public function initDb($server)
    {
        $this->db=$server;
    }
    public function add($data)
    {
        $this->db->add($data);
    }
}

public class UserController
{
    public addUser()
    {
        $user=array();
        Db mysql=new Mysql();
        
        UserModels usermodels=new UserModels();
        usermodels->initDb(mysql);
        usermodels->add($user);
    }
}

 

 

 

发现,这些注入方式的代码 还是不好写,麻烦,想通过配置的方式,底层实现,然后在具体业务上不需要关心我的数据源。。然后 想到了IOC容器,来实现 自动的依赖注入

java 的spring 框架就是用来做这个事情的。可是 我是php 啊。。怎么办咧。。想要自己实现一套 类似的东西。

不想用xml 就用 配置的数组吧。

 

先添加一个配置文件   

Ucontainer.php
<?php
namespace Config;
/**
 * IOC容器配置
 * @author
 */
class Ucontainer
{
    // 
    public static $db = array(
        'UserModels'    => 'Db',// 或者指向  Api
    );


}

 

 

然后添加一个

Ucontainer.php类 来做注入

<?php
namespace Lib;

class UContainer{

    /**
    *@intro 通过配置 获取 数据源对象
    *@author kinmos 
    *@time 
    *@param 
    *@return
    */
    public static function getDbInstanse($models)
    {
        $dbContainer=\Config\Ucontainer::$db;
        if(isset($dbContainer[$models])&&!empty($dbContainer[$models]))
        {
            $source=str_replace('Models','',$models);
            $classname = "\Http\\Models\\".$dbContainer[$models]."\\".$source;
            return new $classname;
        }
    }
}

 

 

 

这样 ,在我们的数据层 。定义的Models 文件夹中添加一个UserModels 文件 

UserModels.php

<?php

namespace Http\Models;
use Lib\UContainer;

class UserModels
{
    private static $classname='UserModels';

    // 获取用户列表
    public static function userList($params=array()){
        
        $data=UContainer::getDbInstanse(self::$classname)->userList();

        return $data;
    }
}

 

 

这样在我们的Models 里面的Db  和 Api 文件夹中各自添加各自方式的数据源

Api.User.php

<?php

namespace Http\Models\Api;

class User
{


    public function userList($apiReqData = array())
    {
        $result = array();
        //组装API请求的数据
        $apiName = 'User.userList'; //接口的名称
        //请求API,得到返回的数据(数组格式)
        $resultEntity = httpApiGetData($apiName, $apiReqData);
        
        if ($resultEntity['code'] == 200) {
            $result = $resultEntity['data'];
        }

        

        return $result;
    }
}

 

Db.User.php

<?php

namespace Http\Models\Db;

use Lib\DbTable;

/**
 * 
 */
class User extends DbTable
{
    protected $_name = 'user';

    protected $_primary = 'id';

    protected $_db = 'default';

    /*
    * 构造函数
    */
    public function __construct()
    {
    }

    public function userList($params=array())
    {
        // 查询所有数据
        $list=$this->getList('1=1');
        return $list;
    }
}

 

 

 

这样 一个整个简单的容器就搭建起来了。然后在使用上就简单了。

namespace Http\Controllers\Demo;

use Http\Models\UserModels;

use Http\Controllers\ActionController;

class IndexController extends ActionController
{
    
    public function index()
    {
        $data=UserModels::userList();
        print_r($data);die;
    }
}

 

 

使用上,只需要调用 Models层的数据,就可以了。业务上不需要关系到底 从那个数据源中取数据,

 

同样的道理,如果 需要 添加sqlserver的数据源,同样的方式 添加一个sqlserver的服务就可以加以注入

 

posted on 2017-06-16 10:05  轻浮不韪  阅读(241)  评论(0编辑  收藏  举报