zoukankan      html  css  js  c++  java
  • Lumen开发:lumen源码解读之初始化(5)——注册(register)与启动(boot)

    版权声明:本文为博主原创文章,未经博主允许不得转载。

    register()是在服务容器注册服务,

    bootstrap/app.php

    /**
       *  注册外部服务
       */
    $app->register(DingoApiProviderLumenServiceProvider::class);
    $app->register(BarryvdhLaravelIdeHelperIdeHelperServiceProvider::class);
    $app->register(MaatwebsiteExcelExcelServiceProvider::class);
    
    /**
       *   注册内部服务
       */
    $app->register(AppProvidersUserUserServiceProvider::class);
    $app->register(AppProvidersValidateValidateServiceProvider::class);
    $app->register(AppProvidersCacheCacheServiceProvider::class);
    
        /**
         * Register a service provider with the application.(申请登记服务提供商)
         *
         * @param  IlluminateSupportServiceProvider|string  $provider
         * @return IlluminateSupportServiceProvider
         */
        public function register($provider)
        {
         if (! $provider instanceof ServiceProvider) {   $provider = new $provider($this); } if (array_key_exists($providerName = get_class($provider), $this->loadedProviders)) { return; } $this->loadedProviders[$providerName] = true; if (method_exists($provider, 'register')) { $provider->register(); } if (method_exists($provider, 'boot')) { return $this->call([$provider, 'boot']); } }
    如果不是继承ServiceProvider,则直接new一个实例,传过去的$this是$app,那边类初始化时可以接收这个对象,然后操作容器;
    如果该服务已注册,则直接返回;
    标记为true;
    如果有register函数则执行:
    如果有boot函数,则调用call函数

        /**
         * Call the given Closure / class@method and inject its dependencies.(调用给定的闭包/类@方法并注入它的依赖项。)
         *
         * @param  callable|string  $callback
         * @param  array  $parameters
         * @param  string|null  $defaultMethod
         * @return mixed
         */
        public function call($callback, array $parameters = [], $defaultMethod = null)
        {
            return BoundMethod::call($this, $callback, $parameters, $defaultMethod);
        }
    
    /**
         * Call the given Closure / class@method and inject its dependencies.(调用给定的闭包/类@方法并注入它的依赖项。)
         *
         * @param  IlluminateContainerContainer  $container
         * @param  callable|string  $callback
         * @param  array  $parameters
         * @param  string|null  $defaultMethod
         * @return mixed
         */
        public static function call($container, $callback, array $parameters = [], $defaultMethod = null)
        {
            if (static::isCallableWithAtSign($callback) || $defaultMethod) {
                return static::callClass($container, $callback, $parameters, $defaultMethod);
            }
    
            return static::callBoundMethod($container, $callback, function () use ($container, $callback, $parameters) {
                return call_user_func_array(
                    $callback, static::getMethodDependencies($container, $callback, $parameters)
                );
            });
        }
    

    第一个判断需要$callback是字符串,一般调不到。

        /**
         * Determine if the given string is in Class@method syntax.(确定给定的字符串是类”方法的语法。)
         *
         * @param  mixed  $callback
         * @return bool
         */
        protected static function isCallableWithAtSign($callback)
        {
            return is_string($callback) && strpos($callback, '@') !== false;
        }
    

    接下来看callBoundMethod方法

        /**
         * Call a method that has been bound to the container.(调用已绑定到容器的方法。)
         *
         * @param  IlluminateContainerContainer  $container
         * @param  callable  $callback
         * @param  mixed  $default
         * @return mixed
         */
        protected static function callBoundMethod($container, $callback, $default)
        {
            if (! is_array($callback)) {
                return $default instanceof Closure ? $default() : $default;
            }
    
            // Here we need to turn the array callable into a Class@method string we can use to
            // examine the container and see if there are any method bindings for this given
            // method. If there are, we can call this method binding callback immediately.
            $method = static::normalizeMethod($callback);
    
            if ($container->hasMethodBinding($method)) {
                return $container->callMethodBinding($method, $callback[0]);
            }
    
            return $default instanceof Closure ? $default() : $default;
        }
    

    判断是否为数组,不是的话,判断是否闭包,直接执行传过来的闭包或类;

    将数组递归化为一个类@方法字符串;

    检查容器,并查看该方法是否有任何方法绑定;

    如果有的话,我们可以调用这个方法立即绑定回调;(好像用来验证的$this->methodBindings一直是空。。。)

    如果没有,判断是否闭包,直接执行传过来的闭包或类;

    我们再来看下调用callBoundMethod时传的闭包吧

    return static::callBoundMethod($container, $callback, function () use ($container, $callback, $parameters) {
                return call_user_func_array(
                    $callback, static::getMethodDependencies($container, $callback, $parameters)
                );
            });
    

    先看下getMethodDependencies方法,

        /**
         * Get all dependencies for a given method.(获取给定方法的所有依赖项。)
         *
         * @param  IlluminateContainerContainer
         * @param  callable|string  $callback
         * @param  array  $parameters
         * @return array
         */
        protected static function getMethodDependencies($container, $callback, array $parameters = [])
        {
            $dependencies = [];
    
            foreach (static::getCallReflector($callback)->getParameters() as $parameter) {
                static::addDependencyForCallParameter($container, $parameter, $parameters, $dependencies);
            }
    
            return array_merge($dependencies, $parameters);
        }
    

     基本都是返回空数组,暂时先不入这个坑了,应该是对给定的回调做反射处理,获取给定调用参数的依赖性。

    return call_user_func_array(
                    $callback, []
                );
    

    那么多数情况,闭包函数执行的就是上面这段,而

    $callback = [$provider, 'boot'];
    

    所以说,就是执行了对应服务的boot方法,后面遇到其他情况,会继续做完善。

    Lumen技术交流群:310493206

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    hexo 建站参考
    如何在element-UI 组件的change事件中传递自定义参数
    vue 项目中当访问路由不存在的时候默认访问404页面
    百度地图引用时 报出A Parser-blocking, cross site (i.e. different eTLD+1) script
    echarts之legend-改变图例的图标为自定义图片
    大数据浪潮下的前端工程师
    为什么要使用TypeScript开发Web应用程序
    【转】简单理解Vue中的nextTick
    vue项目如何刷新当前页面
    安装Genymotion android模拟器
  • 原文地址:https://www.cnblogs.com/cxscode/p/7562853.html
Copyright © 2011-2022 走看看