通过源码解析Laravel的依赖注入

前言

众所周知,php的框架数不胜数,近几年,一个以优雅著称的框架,渐渐被国内phper所知道,并且开始使用,但是larave有一个很明显的缺点就是,他的文档内容少的可怜。

本文将给大家详细介绍关于Laravel依赖注入的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

在 Laravel 的控制器的构造方法或者成员方法,都可以通过类型约束的方式使用依赖注入,如:

public function store(Request $request)
{
 //TODO
}

这里 $request 参数就使用了类型约束,Request 是一个类:\Illuminate\Http\Request,表示参数必须是这个类或子类。

本文通过分析 Laravel 的源码,看为什么方法中不需要传入实例就可以直接使用 Request 呢?只是框架自动帮我们实例化并传参了。

1.路由定义

从源头开始看起,在路由定义文件中定义了这么一个路由:

Route::resource('/role', 'Admin\RoleController');

这是一个资源型的路由,Laravel 会自动生成增删改查的路由入口。

本文开头的 store 方法就是一个控制器的方法,图中可见路由定义的 Action 也是:App\Http\Controllers\Admin\RoleController@store

路由方法解析

根据路由定义找到控制器和方法,执行具体的方法在 dispatch 方法中实现。

(文件:vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php)

public function dispatch(Route $route, $controller, $method)
{
 $parameters = $this->resolveClassMethodDependencies(
  $route->parametersWithoutNulls(), $controller, $method
 );

 if (method_exists($controller, 'callAction')) {
  return $controller->callAction($method, $parameters);
 }

 return $controller->{$method}(...array_values($parameters));
}

首先 resolveClassMethodDependencies 方法,“顾名思义”是根据类的方法参数获取依赖对象,然后再调用类的方法并把对象参数注入。

如果有多个依赖对象,也会 foreach 依次解析出来作为参数注入。

获取依赖对象示例的代码:

protected function resolveClassMethodDependencies(array $parameters, $instance, $method)
{
 if (! method_exists($instance, $method)) {
  return $parameters;
 }

 return $this->resolveMethodDependencies(
  $parameters, new ReflectionMethod($instance, $method)
 );
}

这里重点就是用到了 PHP 的反射,注意 RelectionMethod 方法,它获取到类的方法参数列表,可以知道参数的类型约束,参数名称等等。

这里的 $instance 参数就是 RoleController 控制器类,$method 参数就是方法名称 strore.

2.获取依赖对象的示例

从方法的参数中获取了依赖对象的约束类型,就可以实例化这个依赖的对象。

protected function transformDependency(ReflectionParameter $parameter, $parameters)
{
 $class = $parameter->getClass();
 // If the parameter has a type-hinted class, we will check to see if it is already in
 // the list of parameters. If it is we will just skip it as it is probably a model
 // binding and we do not want to mess with those; otherwise, we resolve it here.
 if ($class && ! $this->alreadyInParameters($class->name, $parameters)) {
  return $parameter->isDefaultValueAvailable()
   ? $parameter->getDefaultValue()
   : $this->container->make($class->name);
 }
}

根据类名从容器中获取对象,这个绑定对象实例的过程在服务提供者中先定义和了。

然后把实例化的对象传入到 store 方法中,就可以使用依赖的对象了。

3.关于 PHP 反射

举个使用 ReflectionMethod 的例子。

class Demo
{
 private $request;
 public function store(Request $request)
 {
 }
}

打印出 new ReflectionMethod(Demo::class, ‘store') 的内容如图:

可以得出这个方法的参数列表,参数的约束类型,如 typeHint,Illuminate\Http\Request.

根据类名可以从容器中获取一开始通过服务提供者绑定的实例。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

您可能感兴趣的文章:

  • Laravel实现构造函数自动依赖注入的方法
(0)

相关推荐

  • Laravel实现构造函数自动依赖注入的方法

    本文实例讲述了Laravel实现构造函数自动依赖注入的方法.分享给大家供大家参考,具体如下: 在Laravel的构造函数中可以实现自动依赖注入,而不需要实例化之前先实例化需要的类,如代码所示: <?php namespace Lio\Http\Controllers\Forum; use Lio\Forum\Replies\ReplyRepository; use Lio\Forum\Threads\ThreadCreator; use Lio\Forum\Threads\ThreadCreat

  • 通过源码解析Laravel的依赖注入

    前言 众所周知,php的框架数不胜数,近几年,一个以优雅著称的框架,渐渐被国内phper所知道,并且开始使用,但是larave有一个很明显的缺点就是,他的文档内容少的可怜. 本文将给大家详细介绍关于Laravel依赖注入的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 在 Laravel 的控制器的构造方法或者成员方法,都可以通过类型约束的方式使用依赖注入,如: public function store(Request $request) { //TODO } 这里

  • .NET Core源码解析配置文件及依赖注入

    写在前面 上篇文章我给大家讲解了ASP.NET Core的概念及为什么使用它,接着带着你一步一步的配置了.NET Core的开发环境并创建了一个ASP.NET Core的mvc项目,同时又通过一个实战教你如何在页面显示一个Content的列表.不知道你有没有跟着敲下代码,千万不要做眼高手低的人哦. 这篇文章我们就会设计一些复杂的概念了,因为要对ASP.NET Core的启动及运行原理.配置文件的加载过程进行分析,依赖注入,控制反转等概念的讲解等. 俗话说,授人以鱼不如授人以渔,所以文章旨在带着大

  • Jwt通过源码揭秘隐藏大坑

    目录 前言 集成JWT 坑在哪里 查看源码探索问题原因 总结 前言 JWT是目前最为流行的接口认证方案之一,有关JWT协议的详细内容,请参考:https://jwt.io/introduction 今天分享一下在使用JWT在项目中遇到的一个问题,主要是一个协议的细节,非常容易被忽略,如果不是自己遇到,或者去看源码的实现,我估计至少80%的人都会栽在这里,下面来还原一下这个问题的过程,由于这个问题出现有一定的概率,不是每次都会出现,所以才容易掉坑里. 集成JWT 在Asp.Net Core中集成J

  • Ubuntu18.04通过源码安装Odoo14的教程

    本系列背景介绍 Odoo 是一个基于Python语言构建的开源软件,面向企业应用的CRM,ERP等领域,其目标是对标SAP,Oracle等大型软件提供商,但却通过仅仅一个平台满足企业所有管理的业务需求. 本系列文章针对Odoo 14版,从系统安装,开发环境配置,代码结构,主要功能升级,源码赏析,Anodoo对Odoo的关键扩展等角度,预先给大家介绍即将在2020年发布的这一最新版本. 本篇概述 Odoo14的安装和历史版本差不多,同样也包括安装文件,源码,Docker等多种形式,本文则通过源码方

  • SpringBoot通过源码探究静态资源的映射规则实现

    我们开发一个Spring Boot项目,肯定要导入许多的静态资源,比如css,js等文件 如果我们是一个web应用,我们的main下会有一个webapp,我们以前都是将所有的页面导在这里面的,对吧!但是我们现在的pom呢,打包方式是为jar的方式,那么这种方式SpringBoot能不能来给我们写页面呢?当然是可以的,但是SpringBoot对于静态资源放置的位置,是有规定的! 1.静态资源映射规则 1.1.第一种映射规则 SpringBoot中,SpringMVC的web配置都在 WebMvcA

  • 如何通过源码了解Java的自动装箱拆箱详解

    目录 什么叫装箱 & 拆箱? 首先看一段代码 装箱(valueOf()) 为什么要有[-128,127]的缓存? 为什么是[-128,127]? 自动装箱带来的性能问题 小总结 拆箱(intValue) 补充:自动装箱.拆箱总是会发生吗? 总结 什么叫装箱 & 拆箱? 将int基本类型转换为Integer包装类型的过程叫做装箱,反之叫拆箱. 首先看一段代码 public static void main(String[] args) { Integer a = 127, b = 127;

  • Spring源码解析之循环依赖的实现流程

    目录 前言 循环依赖实现流程 前言 上篇文章中我们分析完了Spring中Bean的实例化过程,但是没有对循环依赖的问题进行分析,这篇文章中我们来看一下spring是如何解决循环依赖的实现. 之前在讲spring的过程中,我们提到了一个spring的单例池singletonObjects,用于存放创建好的bean,也提到过这个Map也可以说是狭义上的spring容器. private final Map<String, Object> singletonObjects = new Concurr

  • Vue 2源码阅读 Provide Inject 依赖注入详解

    目录 Provide/Inject 初始化 1. initInjections 依赖初始化 2. initProvide 注入数据初始化 总结 Provide/Inject 初始化 1. initInjections 依赖初始化 该步骤其实发生在 initState 之前,但是由于 provide/inject 一般是配合使用,所以这里调整了一下顺序. 该函数的定义与过程都比较简单: export function initInjections(vm: Component) { const re

  • 通过源码分析Golang cron的实现原理

    目录 前言 Demo示例 源码实现 结构体 Cron 和 Entry New()实现 AddFunc()实现 Start()实现 Run()实现 Stop()实现 Remove()实现 小结 前言 golang实现定时任务很简单,只须要简单几步代码即可以完成,最近在做了几个定时任务,想研究一下它内部是怎么实现的,所以将源码过了一遍,记录和分享在此.需要的朋友可以参考以下内容,希望对大家有帮助. 关于go cron是如何使用的可以参考之前的文章:一文带你入门Go语言中定时任务库Cron的使用 De

  • 通过源码分析iOS中的深拷贝与浅拷贝

    前言 关于iOS中对象的深拷贝和浅拷贝的文章有很多,但是大部分都是基于打印内存地址来推导结果,这篇文章是从源码的角度来分析深拷贝和浅拷贝. 深拷贝和浅拷贝的概念 拷贝的方式有两种:深拷贝和浅拷贝. 浅拷贝又叫指针拷贝,比如说有一个指针,这个指针指向一个字符串,也就是说这个指针变量的值是这个字符串的地址,那么此时对这个字符串进行指针拷贝的意思就是又创建了一个指针变量,这个指针变量的值是这个字符串的地址,也就是这个字符串的引用计数+1. 深拷贝又叫内容拷贝,比如有一个指针,这个指针指向一个字符串,也

随机推荐