千家信息网

服务容器Ioc的示例分析

发表于:2025-01-26 作者:千家信息网编辑
千家信息网最后更新 2025年01月26日,小编给大家分享一下服务容器Ioc的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!服务容器是一个用于管理类依赖和执行
千家信息网最后更新 2025年01月26日服务容器Ioc的示例分析

小编给大家分享一下服务容器Ioc的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

服务容器是一个用于管理类依赖和执行依赖注入的强大工具。

一个类要被容器所能够提取,必须要先注册至这个容器。既然称这个容器叫做服务容器,那么我们需要某个服务,就得先注册、绑定这个服务到容器,那么提供服务并绑定服务至容器的东西就是服务提供器(ServiceProvider)。

依赖注入和控制反转是对同一件事情的不同描述,它们描述的角度不同。依赖注入是从应用程序的角度在描述,应用程序依赖容器创建并注入它所需要的外部资源。而控制反转是从容器的角度在描述,容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。

 '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的示例分析"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

0