Lumen开发:lumen源码解读之初始化(5)——注册(register)与启动(boot)
版权声明:本文为博主原创文章,未经博主允许不得转载。
register()是在服务容器注册服务,
bootstrap/app.php
1 2 3 4 5 6 7 8 9 10 11 12 13 | /** * 注册外部服务 */ $app ->register(Dingo\Api\Provider\LumenServiceProvider:: class ); $app ->register(Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider:: class ); $app ->register(Maatwebsite\Excel\ExcelServiceProvider:: class ); /** * 注册内部服务 */ $app ->register(App\Providers\User\UserServiceProvider:: class ); $app ->register(App\Providers\Validate\ValidateServiceProvider:: class ); $app ->register(App\Providers\Cache\CacheServiceProvider:: class ); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | /** * Register a service provider with the application.(申请登记服务提供商) * * @param \Illuminate\Support\ServiceProvider|string $provider * @return \Illuminate\Support\ServiceProvider */ public function register( $provider ) {<br> 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' ]); } } |
1 | 如果不是继承ServiceProvider,则直接 new 一个实例,传过去的 $this 是 $app ,那边类初始化时可以接收这个对象,然后操作容器;<br>如果该服务已注册,则直接返回;<br>标记为true;<br>如果有register函数则执行:<br>如果有boot函数,则调用call函数<br><br> |
1 2 3 4 5 6 7 8 9 10 11 12 | /** * 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 ); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /** * Call the given Closure / class@method and inject its dependencies.(调用给定的闭包/类@方法并注入它的依赖项。) * * @param \Illuminate\Container\Container $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是字符串,一般调不到。
1 2 3 4 5 6 7 8 9 10 | /** * 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方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /** * Call a method that has been bound to the container.(调用已绑定到容器的方法。) * * @param \Illuminate\Container\Container $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时传的闭包吧
1 2 3 4 5 | return static ::callBoundMethod( $container , $callback , function () use ( $container , $callback , $parameters ) { return call_user_func_array( $callback , static ::getMethodDependencies( $container , $callback , $parameters ) ); }); |
先看下getMethodDependencies方法,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /** * Get all dependencies for a given method.(获取给定方法的所有依赖项。) * * @param \Illuminate\Container\Container * @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 ); } |
基本都是返回空数组,暂时先不入这个坑了,应该是对给定的回调做反射处理,获取给定调用参数的依赖性。
1 2 3 | return call_user_func_array( $callback , [] ); |
那么多数情况,闭包函数执行的就是上面这段,而
1 | $callback = [ $provider , 'boot' ]; |
所以说,就是执行了对应服务的boot方法,后面遇到其他情况,会继续做完善。
Lumen技术交流群:310493206
版权声明:本文为博主原创文章,未经博主允许不得转载。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!