laravel框架底层解析

本文参考陈昊《Laravel框架关键技术解析》,搭建一个属于自己的简化版服务容器。
其中涉及到反射、自动加载,还是需要去了解一下。

laravel服务容器

  1. 建立项目空文件夹(如 mylaravel)

  2. 添加composer.json,执行composer install

  1. {
  2. "name": "laravel/laravel",
  3. "description": "The Laravel Framework.",
  4. "keywords": ["framework", "laravel"],
  5. "license": "MIT",
  6. "type": "project",
  7. "autoload": {
  8. "classmap": [
  9. ],
  10. "psr-4": {
  11. "App\\": "app/"
  12. }
  13. }
  14. }

目的是为了学习、利用composer的自动加载。

  1. 文件路径如下所示

  • mylaravel

    • app

      • Traveller

        • Traveller.php

      • Visit

        • Leg.php

        • Visit.php

      • Container.php

      • Index.php

    • vendor

    • composer.json

  1. 简化版Container.php

  1. <?php
  2. namespace App;
  3. Class Container
  4. {
  5. protected $bindings = [];
  6. /**
  7. * 绑定接口和生成相应实例的回调函数
  8. * @param $abstract 服务名称
  9. * @param null $concreate 回调函数或名称
  10. * @param bool $shared 是否为单例
  11. *
  12. */
  13. public function bind($abstract, $concrete = null, $shared = false)
  14. {
  15. if ( ! $concrete instanceof \Closure) {
  16. // 如果提供的参数不是回调函数,则产生默认的回调函数
  17. $concrete = $this->getClosure($abstract, $concrete);
  18. }
  19. $this->bindings[$abstract] = compact('concrete', 'shared');
  20. }
  21. //默认的回调函数
  22. protected function getClosure($abstract, $concrete)
  23. {
  24. //生成实例的回调函数, $c一般为ioc容器对象
  25. return function($c) use ($abstract, $concrete)
  26. {
  27. $method = ($abstract == $concrete) ? 'build' : 'make';
  28. return $c->$method($concrete);
  29. };
  30. }
  31. //生成实例对象,首先解决接口和要实例化类之间的依赖
  32. public function make($abstract)
  33. {
  34. $concrete = $this->getConcrete($abstract);
  35. if ($this->isBuildable($concrete, $abstract)) {
  36. $object = $this->build($concrete);
  37. } else {
  38. $object = $this->make($concrete);
  39. }
  40. return $object;
  41. }
  42. protected function isBuildable($concrete, $abstract)
  43. {
  44. return $concrete === $abstract || $concrete instanceof \Closure;
  45. }
  46. //获取绑定的回调函数
  47. protected function getConcrete($abstract)
  48. {
  49. if ( ! isset($this->bindings[$abstract]))
  50. {
  51. return $abstract;
  52. }
  53. return $this->bindings[$abstract]['concrete'];
  54. }
  55. //实例化对象
  56. public function build($concrete)
  57. {
  58. if ($concrete instanceof \Closure) {
  59. return $concrete($this);
  60. }
  61. $reflector = new \ReflectionClass($concrete);
  62. if ( ! $reflector->isInstantiable()) {
  63. echo $message = "Target [$concrete] is not instantiable.";
  64. }
  65. $constructor = $reflector->getConstructor();
  66. if (is_null($constructor)) {
  67. return new $concrete;
  68. }
  69. $dependencies = $constructor->getParameters();
  70. $instances = $this->getDependencies($dependencies);
  71. return $reflector->newInstanceArgs($instances);
  72. }
  73. protected function getDependencies($parameters)
  74. {
  75. $dependencies = [];
  76. foreach ($parameters as $parameter)
  77. {
  78. $denpendency = $parameter->getClass();
  79. if (is_null($denpendency)) {
  80. $dependencies[] = NULL;
  81. } else {
  82. $dependencies[] = $this->resolveClass($parameter);
  83. }
  84. }
  85. return (array) $dependencies;
  86. }
  87. protected function resolveClass(\ReflectionParameter $parameter)
  88. {
  89. return $this->make($parameter->getClass()->name);
  90. }
  91. }

Visit.php接口

  1. <?php
  2. namespace App\Visit;
  3. interface Visit
  4. {
  5. public function go();
  6. }

Leg.php接口的一种实现

  1. <?php
  2. namespace App\Visit;
  3. Class Leg implements Visit
  4. {
  5. public function go()
  6. {
  7. echo "walk to tibet!";
  8. }
  9. }

Traveller.php相当于Controller下的方法

  1. <?php
  2. namespace App\Traveller;
  3. use App\Visit\Visit;
  4. Class Traveller
  5. {
  6. protected $trafficTool;
  7. //Visit是抽象类,index中将leg注入到了容器,取代了Visit
  8. public function __construct(Visit $visit)
  9. {
  10. $this->trafficTool = $visit;
  11. }
  12. public function visitTibet()
  13. {
  14. $this->trafficTool->go();
  15. }
  16. }

Index.php

  1. <?php
  2. namespace App;
  3. //调用composer的自动加载
  4. require '../vendor/autoload.php';
  5. Class Index
  6. {
  7. public function index()
  8. {
  9. //实例化ioc容器
  10. $app = new Container();
  11. //容器填充
  12. $app->bind('App\Visit\Visit', '\App\Visit\Leg');
  13. $app->bind('Traveller', '\App\Traveller\Traveller');
  14. //通过容器实现依赖注入,完成类的实例化
  15. $tra = $app->make("\App\Traveller\Traveller");
  16. $tra->visitTibet();
  17. }
  18. }
  19. $b = new Index;
  20. $b->index();

laravel服务容器 转的更多相关文章

  1. Laravel 服务容器、服务提供器、契约实例讲解

        前言 刚开始看laravel服务容器.契约.服务提供器的确生涩难懂,不单单是概念繁多,而且实际的demo很难找(找是找到了,但难用啊),最后就隔一段时间看一遍,大概个十来遍,还真给看出个门道, ...

  2. laravel服务容器

    laravel框架底层解析 本文参考陈昊<Laravel框架关键技术解析>,搭建一个属于自己的简化版服务容器.其中涉及到反射.自动加载,还是需要去了解一下. laravel服务容器 建立项 ...

  3. Laravel 服务容器实例教程 —— 深入理解控制反转(IoC)和依赖注入(DI)

    容器,字面上理解就是装东西的东西.常见的变量.对象属性等都可以算是容器.一个容器能够装什么,全部取决于你对该容器的定义.当然,有这样一种容器,它存放的不是文本.数值,而是对象.对象的描述(类.接口)或 ...

  4. Laravel服务容器的绑定与解析

    本篇文章给大家带来的内容是关于Laravel服务容器的绑定与解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言   老实说,第一次老大让我看laravel框架手册的那天早上,我 ...

  5. 关于使用 Laravel 服务容器的优势介绍

    如果说laravel框架的核心是什么,那么无疑是服务容器.理解服务容器的概念,对于我们使用laravel太重要了,应该说是否理解服务容器的概念是区分是否入门laravel的重要条件.因为整个框架正是在 ...

  6. laravel 服务容器实现原理

    前言 通过实现laravel 框架功能,以便深入理解laravel框架的先进思想. 什么是服务容器 服务容器是用来管理类依赖与运行依赖注入的工具.Laravel框架中就是使用服务容器来实现 ** 控制 ...

  7. laravel服务容器-----深入理解控制反转(IoC)和依赖注入(DI)

    首先大家想一想什么是容器,字面意思就是盛放东西的东西,常见的变量,对象属性都是容器,一个容器能够装什么东西,完全在于你对这个容器的定义.有的容器不仅仅只是存文本,变量,而是对象,属性,那么我们通过这种 ...

  8. Laravel 服务容器,IoC,DI

    DI DI 就是常说的依赖注入,那么究竟什么是依赖注入呢? 打个比方,电脑(非笔记本哈)需要键盘和鼠标我们才能进行操作,这个‘需要’换句话说就是‘依赖’键盘和鼠标. 那么,相应的,一个类需要另一个类才 ...

  9. laravel 服务容器

    服务容器,也叫IOC容器,其实包含了依赖注入(DI)和控制反转(IOC)两部分,是laravel的真正核心.其他的各种功能模块比如 Route(路由).Eloquent ORM(数据库 ORM 组件) ...

随机推荐

  1. 单链表的前K个的逆序输出

    单链表逆序输出也是常被面试官问到题算法题,所以自己就总结了一下,在此贴出算法,与小伙伴们相互交流. 首先要有三个指针,前两个分别指向首节点,首节点的下一个节点,第三个是临时指针,是为了储存首节点的下一 ...

  2. Vue iview Tree组件实现文件目录-基础实现

    注册页面路由 router/router.js { path: 'folder_tree', name: 'folderTree', component: () => import('@/vie ...

  3. python的多种魔术方法

    目录 new str & repr iter getitem.setitem.delitem getattr.setattr.delattr call slots 定制类和魔法方法 new s ...

  4. docker zookeeper 集群搭建

    #创建集群目录 mkdir /opt/cluster/zk cd /opt/cluster/zk #清理脏数据[可跳过] docker stop zk-2181 docker stop zk-2182 ...

  5. 项目升级springboot2.0注意事项

    一.pring boot 2.0以后, springboot jpa findById 返回类型变化@NoRepositoryBeanpublic interface CrudRepository&l ...

  6. JUC 常用4大并发工具类

    什么是JUC? JUC就是java.util.concurrent包,这个包俗称JUC,里面都是解决并发问题的一些东西 该包的位置位于java下面的rt.jar包下面 4大常用并发工具类: Count ...

  7. JavaScript,你好!(二)

    操作BOM对象 浏览器介绍 JavaScript和浏览器的关系? JavaScrpit诞生就是为了能够让它在浏览器中运行! BOM:浏览器对象模型 IE 6~11 Chrome Safari Fire ...

  8. 基于NPOI的Excel导入导出类库

    概述 支持多sheet导入导出.导出字段过滤.特性配置导入验证,非空验证,唯一验证,错误标注等 用于基础配置和普通报表的导入导出,对于复杂需求,比如合并列,公式,导出图片等暂不支持 GitHub地址: ...

  9. node核心模块-vm

    vm vm是node的一个核心模块,核心功能官方文档介绍是: The vm module provides APIs for compiling and running code within V8 ...

  10. 腾讯一面!说说ArrayList的遍历foreach与iterator时remove的区别,我一脸懵逼

    本文基于JDK-8u261源码分析 1 简介 ​ ArrayList作为最基础的集合类,其底层是使用一个动态数组来实现的,这里"动态"的意思是可以动态扩容(虽然ArrayList可 ...