溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

服務容器Ioc的示例分析

發布時間:2021-12-27 10:52:46 來源:億速云 閱讀:216 作者:小新 欄目:大數據

小編給大家分享一下服務容器Ioc的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

服務容器是一個用于管理類依賴和執行依賴注入的強大工具。

一個類要被容器所能夠提取,必須要先注冊至這個容器。既然稱這個容器叫做服務容器,那么我們需要某個服務,就得先注冊、綁定這個服務到容器,那么提供服務并綁定服務至容器的東西就是服務提供器(ServiceProvider)。

依賴注入和控制反轉是對同一件事情的不同描述,它們描述的角度不同。依賴注入是從應用程序的角度在描述,應用程序依賴容器創建并注入它所需要的外部資源。而控制反轉是從容器的角度在描述,容器控制應用程序,由容器反向的向應用程序注入應用程序所需要的外部資源。

<?php

/**
 * Interface Log
 * 面向接口編程
 */
interface Log
{
    public function write();
}

class FileLog implements Log
{
    public function write()
    {
        echo 'filelog write...' . PHP_EOL;
    }
}

class DataBaseLog implements Log
{
    public function write()
    {
        echo 'dblog write...' . PHP_EOL;
    }
}

/**
 * Class Request
 * 模擬請求類
 */
class Request
{
    public function toArray()
    {
        return ['name' => 'value'];
    }
}

/**
 * User類依賴Log接口的實現
 */
class User
{
    private $log;
    private $extra;

    public function __construct(Log $log, $a, $b, $c = '默認參數')
    {
        $this->log = $log;
        $this->extra = compact('a', 'b', 'c');
    }

    /**
     * 模擬用戶登錄寫入登錄日志
     */
    public function login(Request $request)
    {
        echo '接收登錄請求的參數json:' . json_encode($request->toArray()) . PHP_EOL;
        echo 'user log success...' . PHP_EOL;
        $this->log->write();
    }

    public function getExtra()
    {
        var_dump($this->extra);
    }
}


/**
 * Class Ioc
 * 模擬IoC容器
 * 類從注冊到實例化,最終被我們所使用,都是服務容器負責
 */
class Ioc
{
    protected $bindings = [];
    protected $instances = [];
    protected static $ioc;

    protected function __construct()
    {
    }

    public static function getInstance()
    {
        if (is_null(self::$ioc)) {
            self::$ioc = new self();
        }
        return self::$ioc;
    }

    /**
     * 注冊綁定 (綁定自身、閉包、接口)
     * 也就是服務
     * @param $abstract
     * @param null $concrete
     * @param bool $share
     */
    public function bind($abstract, $concrete = null, $share = true)
    {
        if (is_null($concrete)) {
            $concrete = $abstract;
        }
        $this->bindings[$abstract]['share'] = $share;
        if ($concrete instanceof Closure) {
            $this->bindings[$abstract]['concrete'] = $concrete;
        } else {
            $this->bindings[$abstract]['concrete'] = function (Ioc $ioc, $vars = []) use ($concrete) {
                return $ioc->build($concrete, $vars);
            };
        }
    }

    /**
     * 返回對象
     * @param $abstract
     * @param array $vars
     * @return mixed
     * @throws ReflectionException
     */
    public function make($abstract, $vars = [])
    {
        if (isset($this->instances[$abstract])) {
            return $this->instances[$abstract];
        }

        if (isset($this->bindings[$abstract]['concrete'])) {
            $concrete = $this->bindings[$abstract]['concrete'];
            $instance = $concrete($this, $vars);
            if ($this->bindings[$abstract]['share']) {
                $this->instances[$abstract] = $instance;
            }
            return $instance;
        }

        throw new RuntimeException($abstract . ' is not bound yet');
    }

    /**
     * 創建對象
     * @param $concrete
     * @return object
     * @throws ReflectionException
     */
    public function build($concrete, $vars = [])
    {
        $reflectionClass = new ReflectionClass($concrete);
        $constructor = $reflectionClass->getConstructor();
        if (is_null($constructor)) {
            return $reflectionClass->newInstance();
        }
        $isInstantiable = $reflectionClass->isInstantiable();
        if (!$isInstantiable) {
            throw new ReflectionException("{$concrete} cant construct");
        }
        $parameters = $constructor->getParameters();
        $dependencies = $this->getDependencies($parameters, $vars);
        return $reflectionClass->newInstanceArgs($dependencies);
    }

    /**
     * 獲取參數的依賴
     * @param array $parameters
     * @return array
     * @throws ReflectionException
     */
    public function getDependencies(array $parameters, $vars = [])
    {
        $dependencies = [];
        reset($vars);
        $type = key($vars) === 0 ? 'figure' : 'letter';
        /**
         * @var ReflectionParameter $parameter
         */
        foreach ($parameters as $parameter) {
            $dependency = $parameter->getClass();
            $name = $parameter->getName();
            if ($dependency) {
                $dependencies[] = $this->getObjectParam($dependency->getName(), $vars);
            } elseif ('figure' == $type && !empty($vars)) {
                $dependencies[] = array_shift($vars);
            } elseif ('letter' == $type && isset($vars[$name])) {
                $dependencies[] = $vars[$name];
            } elseif ($parameter->isDefaultValueAvailable()) {
                $dependencies[] = $parameter->getDefaultValue();
            } else {
                throw new ReflectionException('The constructor of the ' . $parameter->getDeclaringClass()->getName() . ' class has no default value of $' . $name);
            }
        }

        return $dependencies;
    }

    /**
     * 獲取對象類型的參數值
     * @access protected
     * @param string $className 類名
     * @param array $vars 參數
     * @return mixed
     */
    protected function getObjectParam($className, &$vars)
    {
        $array = $vars;
        $value = array_shift($array);
        if ($value instanceof $className) {
            $result = $value;
            array_shift($vars);
        } else {
            $result = $this->make($className);
        }

        return $result;
    }

    /**
     * @param null $key
     * @return array|mixed|null
     */
    public function getInstances($key = null)
    {
        if (is_null($key)) {
            return $this->instances;
        } elseif (isset($this->instances[$key])) {
            return $this->instances[$key];
        } else {
            return null;
        }
    }
}


// run
/*
 | 模擬容器綁定
 */
$ioc = Ioc::getInstance();
$ioc->bind(Request::class);//綁定類
$ioc->bind(Log::class, FileLog::class);//綁定接口
//$ioc->bind(Log::class, DataBaseLog::class);
$ioc->bind('test', function () {//綁定閉包
    return 'test' . PHP_EOL;
});

/*
 | 模擬路由訪問 User 控制器下的 login 方法
 */
$ioc->bind(User::class, null, true);
$method = 'login';
$reflectionMethod = new ReflectionMethod(User::class, $method);
$parameters = $reflectionMethod->getParameters();
$dependencies = $ioc->getDependencies($parameters);
$user = $ioc->make(User::class, ['參數1', '參數2']);
call_user_func_array([$user, $method], $dependencies);
// 查看參數
$user->getExtra();
var_dump($ioc->getInstances());

以上是“服務容器Ioc的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

ioc
AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女