依赖注入,简单说是把类里头依赖的对象,置于类外头,即客户端调用处。相当于把类与类解耦。

  一个简单的例子:

  

  1. class A {
  2.  
  3. public function __construct() {
  4. // 这种实例化写法, A类的内部,依赖了B类 需要解耦
  5. $this->b = new B();
  6. }
  7.  
  8. public function say(){
  9. $this->b->talk();
  10. }
  11. }
  12.  
  13. class B{
  14.  
  15. public function __construct() {
  16.  
  17. }
  18.  
  19. public function talk(){
  20. echo __METHOD__;
  21. }
  22. }
  23.  
  24. $a = new A;
  25. $a->say();

  A类依赖B类,耦合较重。

  换一种写法:

  

  1. class A {
  2.  
  3. public function __construct(B $b) {// B的实例化,放在客户端,当作构造参数传递过来
  4. $this->b = $b;
  5. }
  6.  
  7. public function say(){
  8. $this->b->talk();
  9. }
  10. }
  11.  
  12. class B{
  13. public function __construct() {
  14. }
  15.  
  16. public function talk(){
  17. echo __METHOD__;
  18. }
  19. }
  20.  
  21. $b = new B;// 在客户端实例化B
  22. $a = new A($b);// 构造器中传递
  23. $a->say();

这个代码,就相当于实例化B的步骤放在了A类的外部,从而实现解耦。这就是依赖注入的一种实现方式。

Laravel框架中,通过这种依赖注入的方式,再配合反射功能,实现功能。

比如在Laravel的容器类,Container.php(vendor/laravel/framework/src/illuminate/Container/Container.php)中

利用反射,实例化注入的类。

来一段代码:

  1. /**
  2. *
  3. * 依赖注入的思想,把外部依赖的类放在构造函数的参数里
  4. *
  5. * Laravel框架根据反射 搞定依赖
  6. */
  7.  
  8. class Test{
  9.  
  10. public function __construct(Para $p1, Parb $p2) {
  11. echo $p1->getInfo()," ",$p2->getInfo()," ";
  12. }
  13.  
  14. function say(){
  15. echo __CLASS__;
  16. return;
  17. }
  18. }
  19.  
  20. /**
  21. * Class Para
  22. * 参数A
  23. */
  24. class Para {
  25.  
  26. function getInfo() {
  27. echo __CLASS__;
  28. }
  29. }
  30.  
  31. /**
  32. * Class Parb
  33. * 参数B
  34. */
  35. class Parb {
  36.  
  37. function getInfo(){
  38. echo __CLASS__;
  39. }
  40. }
  41.  
  42. $obj = new Test(new Para(), new Parb());
  43.  
  44. // ===================================================
  45.  
  46. $reflector = new ReflectionClass($obj);// 对象 反射其类信息
  47. $constructor = $reflector->getConstructor();
  48.  
  49. $dependencies = $constructor->getParameters();// 获取构造器下的参数信息
  50. $parArr = array();
  51. foreach ($dependencies as $depend){
  52. // $depend->getClass()->name 获取类名称 构造器参数是类
  53. $parArr[] = new ($depend->getClass()->name)();
  54. }
  55.  
  56. $refNew = $reflector->newInstanceArgs($parArr);// Test 对象
  57.  
  58. $refNew->say();

代码中,获取$obj反射后的类信息,再取其构造器中的依赖类,实例化这些依赖类,再传入Test类中。  

这就是Laravel容器中实现的依赖注入和反射应用。

下边的代码有助于理解Laravel框架下的容器Container概念。参考自文章:https://www.insp.top/article/learn-laravel-container

  1. <?php
  2.  
  3. interface SuperModuleInterface{
  4. public function activate(array $target);
  5. }
  6.  
  7. class Superman
  8. {
  9. protected $module;
  10.  
  11. /**
  12. * Superman constructor.
  13. * @param SuperModuleInterface $module
  14. * 通过构造器 注入依赖
  15. */
  16. public function __construct(SuperModuleInterface $module)
  17. {
  18. $this->module = $module;
  19. }
  20.  
  21. public function show(array $target){
  22.  
  23. $this->module->activate($target);
  24. }
  25. }
  26.  
  27. class PowerA implements SuperModuleInterface
  28. {
  29. public function activate(array $target)
  30. {
  31. echo '<pre>'. __METHOD__;
  32. print_r(func_get_args());
  33. }
  34. }
  35.  
  36. class PowerB implements SuperModuleInterface
  37. {
  38. public function activate(array $target)
  39. {
  40. echo '<pre>'. __METHOD__;
  41. print_r(func_get_args());
  42. }
  43. }
  44.  
  45. class Container
  46. {
  47. protected $binds;
  48.  
  49. protected $instances;
  50.  
  51. /**
  52. * @param $abstract
  53. * @param $concrete
  54. * 把代词 绑定到容器里,为后续make
  55. */
  56. public function bind($abstract, $concrete)
  57. {
  58. if ($concrete instanceof Closure) {
  59. $this->binds[$abstract] = $concrete;
  60. } else {
  61. $this->instances[$abstract] = $concrete;
  62. }
  63. }
  64.  
  65. /**
  66. * @param $abstract
  67. * @param array $parameters
  68. * @return mixed
  69. * 创建对象
  70. */
  71. public function make($abstract, $parameters = [])
  72. {
  73. if (isset($this->instances[$abstract])) {
  74. return $this->instances[$abstract];
  75. }
  76. // 把容器对象$this,放到参数数组第一个元素。为call_user_func_array使用
  77. array_unshift($parameters, $this);
  78.  
  79. // 这里$this->binds[$abstract] 绑定的闭包函数, 执行函数参数是$parameters
  80. return call_user_func_array($this->binds[$abstract], $parameters);
  81. }
  82. }
  83.  
  84. // 创建一个容器(后面称作超级工厂)
  85. $container = new Container;
  86.  
  87. // 向该 超级工厂添加超能力模组的生产脚本
  88. $container->bind('powerA', function($container) {
  89. return new PowerA;
  90. });
  91.  
  92. // 同上
  93. $container->bind('powerB', function($container) {
  94. return new PowerB;
  95. });
  96.  
  97. // 向该 超级工厂添加超人的生产脚本
  98. $container->bind('superman', function($container, $moduleName) {
  99. return new Superman($container->make($moduleName));
  100. });
  101.  
  102. echo "<pre>";
  103.  
  104. // 开始启动生产
  105. $superman_1 = $container->make('superman', ['powerA']);
  106. $superman_1->show(['a' => 1]);
  107.  
  108. $superman_2 = $container->make('superman', ['powerB']);
  109. $superman_2->show(['b' => 1]);

Laravel框架下容器Container 的依赖注入和反射应用的更多相关文章

  1. laravel框架中所用到的依赖注入

    用Laravel开发前前后后有2个月左右了,之前一直写Java,就像找到Java和PHP之前的共同点,用Java的某些原理去理解PHP会发现还是有很多共通之处的.Java的依赖注入已经是一个很常见的概 ...

  2. [转载]Spring下IOC容器和DI(依赖注入) @Bean及@Autowired

    Spring下IOC容器和DI(依赖注入) @Bean及@Autowired自动装配 bean是什么 bean在spring中可以理解为一个对象.理解这个对象需要换一种角度,即可将spring看做一门 ...

  3. Laravel框架下路由的使用(源码解析)

    本篇文章给大家带来的内容是关于Laravel框架下路由的使用(源码解析),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 我的解析文章并非深层次多领域的解析攻略.但是参考着开发文 ...

  4. 基于Laravel框架下使用守护进程supervisor实现定时任务(毫秒)

    本篇文章给大家带来的内容是关于基于Laravel框架下使用守护进程supervisor实现定时任务(毫秒),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 公司需要实现X分钟内每隔Y秒 ...

  5. 如何把对象手动注入Spring容器并实现依赖注入

    将对象注入到Spring容器并实现依赖注入 public class UserDao { @Resource AccountService accountService; public void pr ...

  6. 【框架学习与探究之依赖注入--Autofac】

    声明 本文欢迎转载,原文地址:http://www.cnblogs.com/DjlNet/p/7603642.html 序 同样的又是一个双11如期而至,淘宝/天猫实时数据显示,开场3分钟总交易额突破 ...

  7. 解析Laravel框架下的Contracts契约

    Contracts Laravel 的契约是一组定义框架提供的核心服务的接口, 例如我们在介绍用户认证的章节中到的用户看守器契约IllumninateContractsAuthGuard 和用户提供器 ...

  8. 初识Spring框架实现IOC和DI(依赖注入)

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的, IoC是 ...

  9. Spring:Spring-IOC容器、DI依赖注入简介

    Spring容器到底是什么? 从概念上讲:Spring 容器是 Spring 框架的核心,是用来管理对象的.容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁. 从具象化 ...

随机推荐

  1. 使用yum安装不知道到底安装在什么文件夹

    find /* >yum001    #记录之前的文件夹 find /* >yum002    #记录安装完成后的文件夹 diff yum001 yum002 >yum000     ...

  2. sysbench的框架实现介绍

    sysbench是一个非常经典的综合性能测试工具,它支持CPU,IO,内存,尤其是数据库的性能测试.那它是怎么做到通用性的呢,总结一句话是大量运用了重载的方法. sysbench总体架构 sysben ...

  3. SQL优化总结之一

    一.实践中如何优化mysql 1) SQL语句及索引的优化 2) 数据库表结构的优化 3) 系统配置的优化 4) 硬件优化 二.索引的底层实现原理和优化 2.1 底层实现 在DB2数据库中索引采用的是 ...

  4. 在ASP.NET MVC 项目中 使用 echarts 画统计图

    echarts 官方地址:http://echarts.baidu.com/ 一.根据图中的数据怎么从数据库中获取并组装成对应格式: 从数据库中获取对应数据,然后在项目中引用Newtonsoft.Js ...

  5. 【WebAPI No.3】API的访问控制IdentityServer4

    介绍: IdentityServer是一个OpenID Connect提供者 - 它实现了OpenID Connect和OAuth 2.0协议.是一种向客户发放安全令牌的软件. 官网给出的功能解释是: ...

  6. 解决基于IIS的.net core HttpWebRequest 连接特别慢

    用的是HttpWebRequest 连接特别慢,查找原因发现 : 由 HttpWebRequest. Proxy  代理的原因导致 . 其实请求1秒就完成了,那15秒是用来等待默认proxy超时的…… ...

  7. react 插槽(Portals)

    前言: 昨天刚看了插槽,以为可以解决我工作中遇到的问题,非常激动,我今天又仔细想了想,发现并不能解决... 不过还是记录一下插槽吧,加深印象,嗯,就酱. 插槽作用: 插槽即:ReactDOM.crea ...

  8. ssm基础搭建步骤

    今天搭建新的项目环境,从网上找了些ssm的搭建步骤,终于找到了一位csdn的大佬,可以说写的特别详细,按照上面步骤搭建即可,为了方便日后参考,转载到本人博客,原文链接:https://blog.csd ...

  9. iOS----------常见宏定义

    在我们日常的项目中,合理的使用宏定义,会大大减少我们的代码量,以及代码的可读性,为方便读者使用,总结如下: pragma mark - Application相关 ///=============== ...

  10. C#字符串倒置函数的代码

    把内容过程比较常用的内容珍藏起来,下边内容内容是关于C#字符串倒置函数的内容. public static string Reverse(string ReverseString) { String ...