zoukankan      html  css  js  c++  java
  • laravel服务容器 转

     

    laravel框架底层解析

    本文参考陈昊《Laravel框架关键技术解析》,搭建一个属于自己的简化版服务容器。
    其中涉及到反射、自动加载,还是需要去了解一下。

    laravel服务容器

    1. 建立项目空文件夹(如 mylaravel)

    2. 添加composer.json,执行composer install

    {
        "name": "laravel/laravel",
        "description": "The Laravel Framework.",
        "keywords": ["framework", "laravel"],
        "license": "MIT",
        "type": "project",
        "autoload": {
            "classmap": [
            ],
            "psr-4": {
                "App\": "app/"
            }
        }
    }
    

    目的是为了学习、利用composer的自动加载。

    1. 文件路径如下所示

    • mylaravel

      • app

        • Traveller

          • Traveller.php

        • Visit

          • Leg.php

          • Visit.php

        • Container.php

        • Index.php

      • vendor

      • composer.json

    1. 简化版Container.php

    <?php
    namespace App;
    
    Class Container
    {
        protected $bindings = [];
    
        /**
         * 绑定接口和生成相应实例的回调函数
         * @param $abstract 服务名称
         * @param null $concreate 回调函数或名称
         * @param bool $shared 是否为单例
         *
         */
        public function bind($abstract, $concrete = null, $shared = false)
        {
            if ( ! $concrete instanceof Closure) {
                // 如果提供的参数不是回调函数,则产生默认的回调函数
                $concrete = $this->getClosure($abstract, $concrete);
            }
        
            $this->bindings[$abstract] = compact('concrete', 'shared');
        
        }
        //默认的回调函数
        protected function getClosure($abstract, $concrete)
        {
            //生成实例的回调函数, $c一般为ioc容器对象
            return function($c) use ($abstract, $concrete)
            {
                $method = ($abstract == $concrete) ? 'build' : 'make';
                return $c->$method($concrete);
            };
        }
        //生成实例对象,首先解决接口和要实例化类之间的依赖
        public function make($abstract)
        {
            $concrete = $this->getConcrete($abstract);
            if ($this->isBuildable($concrete, $abstract)) {
                $object = $this->build($concrete);
            } else {
                $object = $this->make($concrete);
            }
            return $object;
        }
        protected function isBuildable($concrete, $abstract)
        {
            return $concrete === $abstract || $concrete instanceof Closure;
        }
        //获取绑定的回调函数
        protected function getConcrete($abstract)
        {
            if ( ! isset($this->bindings[$abstract]))
            {
                return $abstract;
            }
            return $this->bindings[$abstract]['concrete'];
        }
        //实例化对象
        public function build($concrete)
        {
            if ($concrete instanceof Closure) {
                return $concrete($this);
            }
            $reflector = new ReflectionClass($concrete);
            if ( ! $reflector->isInstantiable()) {
                echo $message = "Target [$concrete] is not instantiable.";
            }
            $constructor = $reflector->getConstructor();
            if (is_null($constructor)) {
                return new $concrete;
            }
            $dependencies = $constructor->getParameters();
            $instances = $this->getDependencies($dependencies);
            return $reflector->newInstanceArgs($instances);
        }
        protected function getDependencies($parameters)
        {
            $dependencies = [];
            foreach ($parameters as $parameter)
            {
                $denpendency = $parameter->getClass();
                if (is_null($denpendency)) {
                    $dependencies[] = NULL;
                } else {
                    $dependencies[] = $this->resolveClass($parameter);
                }
            }
            return (array) $dependencies;
        }
        protected function resolveClass(ReflectionParameter $parameter)
        {
            return $this->make($parameter->getClass()->name);
        }
    }

    Visit.php接口

    <?php
    namespace AppVisit;
    
    interface Visit
    {
        public function go();
    }

    Leg.php接口的一种实现

    <?php
    namespace AppVisit;
    
    Class Leg implements Visit
    {
        public function go()
        {
            echo "walk to tibet!";
        }
    }

    Traveller.php相当于Controller下的方法

    <?php
    namespace AppTraveller;
    
    use AppVisitVisit;
    
    Class Traveller
    {
        protected $trafficTool;
        //Visit是抽象类,index中将leg注入到了容器,取代了Visit
        public function __construct(Visit $visit)
        {
            $this->trafficTool = $visit;
        }
        public function visitTibet()
        {
            $this->trafficTool->go();
        }
    }

    Index.php

    <?php 
    namespace App;
    
    //调用composer的自动加载
    require '../vendor/autoload.php';
    
    Class Index
    {
        public function index()
        {
                //实例化ioc容器
                $app = new Container();
                //容器填充
                $app->bind('AppVisitVisit', 'AppVisitLeg');
                $app->bind('Traveller', 'AppTravellerTraveller');
                //通过容器实现依赖注入,完成类的实例化
                $tra = $app->make("AppTravellerTraveller");
                $tra->visitTibet();
        }
    }
    
    $b = new Index;
    $b->index();

  • 相关阅读:
    hihocoder #1138 : Islands Travel
    关于c中的inline
    LUOGU P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm
    LUOGU P1908 逆序对
    归并排序 (模板)
    tyvj 1864 守卫者的挑战
    loj #10001. 「一本通 1.1 例 2」种树
    bzoj 1026: [SCOI2009]windy数
    BZOJ 4521: [Cqoi2016]手机号码
    LUOGU 3089 后缀排序(模板)
  • 原文地址:https://www.cnblogs.com/brady-wang/p/10658209.html
Copyright © 2011-2022 走看看