服务容器实例化后,就可以通过服务容器来自动实例化对象了。于是,Kernel类就通过服务容器自动化创建而成,即index.php文件中的“$kernel=$app->make(Illuminate\Contracts\Http\Kernel::class);”。那么我们又在什么时候注册的服务呢?前面已经介绍过,在laravel\bootstrap\app.php文件中,实例化服务容器之后就注册了三个服务,其中就包括这个核心类接口。在注册服务时,服务名一般是接口。在Contracts命名空间下存储的都是接口,而提供的服务则是具体类、实例对象或返回实例对象的回调函数。
由于注册的服务只是具体类名,所以可以通过反射机制来实例化,并通过反射机制自动解决构造函数中的依赖关系。于是,通过服务容器实例化App\Http\Kernel类时,这个类只是定义了$middleware(中间件)和$routeMiddleware(路由中间件)两个数组属性,其中中间件是请求进入路由处理前的处理类,而路由中间件是请求进入路由处理后的处理类,所以这里可以添加新的中间件处理类,只要按照中间件的设计原则进行设计,并在中间件数组的正确位置添加类名,在处理请求的过程中就会调用新添加的中间件处理过程。可以看到,Laravel框架对于扩展就是这么简单,这也得益于框架设计的艺术性。因为App\Http\Kernel类继承了Illuminate\Foundation\Http\Kernel类,所以实例化过程中会调用该类中的构造函数,下面是构造函数源码。文件Illuminate\Foundation\Http\Kernel.php
可以看到,Kernel类的构造函数是存在依赖的,两个依赖分别是Illuminate\Contracts\Foundation\Application和Illuminate\Routing\Router类型,这里依赖的类型要加上命名空间才能正确定义。其中,对于Illuminate\Contracts\Foundation\Application类名我们定义了别名,核心类别名中定义的服务名为“app”,而名称为“app”的服务在注册基础绑定过程中已经注册了,即为服务容器的实例;对于Illuminate\Routing\Router类也注册了别名为“router”,而名为“router”的服务则是在注册基础服务提供者RoutingServiceProvider类的register()函数中注册的,即获取Illuminate\Routing\Router类的实例。在实例化路由类(Router)的时候还会存在依赖,依然通过服务容器自动生成。这里我们看到了服务提供者和服务容器是如何配合来完成依赖注入的整个过程。完成了服务容器和核心类(Kernel类)的实例化之后,接下来该处理请求了,这才是我们的目标。