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

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

  • 相关阅读:
    EntityFramework 启用迁移 EnableMigrations 报异常 "No context type was found in the assembly"
    JAVA 访问FTP服务器示例(2)
    NuGet Package Manager 更新错误解决办法
    JAVA 访问FTP服务器示例(1)
    RemoteAttribute 的使用问题
    诡异的 javascript 变量
    javascript apply用法
    Babun 中文乱码
    GSM呼叫过程
    转站博客园
  • 原文地址:https://www.cnblogs.com/cxscode/p/7562853.html
Copyright © 2011-2022 走看看