laravel容器包括控制反转和依赖注入。要使用它,首先要绑定对象,需要的时候直接用make去取就可以了。通常我们的调用是这样的:$config=$container->make('config');$connection=newConnection($this->config);比较容易理解,这样做的好处是不需要直接创建实例,方法传递的值没有任何变化,这个实例可以在多处共享。但这与依赖注入有什么关系呢?在真正的依赖注入中,不需要给方法传递任何参数值,只需要指定方法参数类型,代码就会自动找到关系,自动注入依赖。这个特性可以在laravel的Controller、Job等中体现出来,如下:Kernel从index.php,通过多层Kernel管道调用,再到Router,通过多层中间件管道调用。最后找到Illuminate/Routing/Route.php的第124行。publicfunctionrun(Request$request){$this->container=$this->container?:newContainer;尝试{if(!is_string($this->action['uses'])){return$this->runCallable($request);}if($this->customDispatcherIsBound()){return$this->runWithCustomDispatcher($request);}return$this->runController($request);}catch(HttpResponseException$e){return$e->getResponse();}}判断是否$this->action['uses'](格式行如:\App\Http\Controller\Datacenter\RealTimeController@anyConsole)是一个字符串,$this->customDispatcherIsBound判断是否绑定了User-definedroutes。然后跳转到$this->runController($request)。protectedfunctionrunController(Request$request){list($class,$method)=explode('@',$this->action['uses']);$parameters=$this->resolveClassMethodDependencies($this->parametersWithoutNulls(),$class,$method);if(!method_exists($instance=$this->container->make($class),$method)){thrownewNotFoundHttpException;}returncall_user_func_array([$instance,$method],$parameters);}$this->resolveClassMethodDependencies这个方法看名字就知道是我们要找的方法。$this->parametersWithoutNulls()是过滤空字符,$class,$method行分别如:\App\Http\Controller\Datacenter\RealTimeController和anyConsole。受保护函数resolveClassMethodDependencies(array$parameters,$instance,$method){if(!method_exists($instance,$method)){return$parameters;}return$this->resolveMethodDependencies($parameters,newReflectionMethod($instance,$method)));}newReflectionMethod($instance,$method)是获取类方法的反射对象,见文档:http://www.php.net/manual/zh/class.reflectionmethod.php跳转到照亮/Routing/RouteDependencyResolverTrait.php第54行。foreach($reflector->getParameters()as$key=>$parameter){$instance=$this->transformDependency($parameter,$parameters,$originalParameters);if(!is_null($instance)){$this->spliceIntoParameters($parameters,$key,$instance);}}return$parameters;}通过反射类方法获取类参数数组,然后遍历传递给$this->transformDependency方法。如果获取不到实例,调用$this->spliceIntoParameters清除参数。保护函数transformDependency(ReflectionParameter$parameter,$parameters,$originalParameters){$class=$parameter->getClass();if($class&&!$this->alreadyInParameters($class->name,$parameters)){return$this->container->make($class->name);}}终于看到了容器的影子,没错,最终的对象还是通过容器的make方法取出来的。至此,参数构造完成,最终会被runController方法的call_user_func_array回调。总结:1.依赖注入的原理其实就是利用类方法反射获取参数类型,然后利用容器构造好实例。然后使用回调函数调用起来。2、注入的对象构造器不能有参数。否则会报错。Missingargument13.依赖注入固然好,但必须由Router类调用,否则不能直接用new实现注入。所以这就是为什么只有Controller和Job类可以使用此功能的原因。
