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

  一个简单的例子:

  

class A {

    public function __construct() {
// 这种实例化写法, A类的内部,依赖了B类 需要解耦
$this->b = new B();
} public function say(){
$this->b->talk();
}
} class B{ public function __construct() { } public function talk(){
echo __METHOD__;
}
} $a = new A;
$a->say();

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

  换一种写法:

  

class A {

    public function __construct(B $b) {// B的实例化,放在客户端,当作构造参数传递过来
$this->b = $b;
} public function say(){
$this->b->talk();
}
} class B{
public function __construct() {
} public function talk(){
echo __METHOD__;
}
} $b = new B;// 在客户端实例化B
$a = new A($b);// 构造器中传递
$a->say();

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

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

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

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

来一段代码:

/**
*
* 依赖注入的思想,把外部依赖的类放在构造函数的参数里
*
* Laravel框架根据反射 搞定依赖
*/ class Test{ public function __construct(Para $p1, Parb $p2) {
echo $p1->getInfo()," ",$p2->getInfo()," ";
} function say(){
echo __CLASS__;
return;
}
} /**
* Class Para
* 参数A
*/
class Para { function getInfo() {
echo __CLASS__;
}
} /**
* Class Parb
* 参数B
*/
class Parb { function getInfo(){
echo __CLASS__;
}
} $obj = new Test(new Para(), new Parb()); // =================================================== $reflector = new ReflectionClass($obj);// 对象 反射其类信息
$constructor = $reflector->getConstructor(); $dependencies = $constructor->getParameters();// 获取构造器下的参数信息
$parArr = array();
foreach ($dependencies as $depend){
// $depend->getClass()->name 获取类名称 构造器参数是类
$parArr[] = new ($depend->getClass()->name)();
} $refNew = $reflector->newInstanceArgs($parArr);// Test 对象 $refNew->say();

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

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

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

<?php

interface SuperModuleInterface{
public function activate(array $target);
} class Superman
{
protected $module; /**
* Superman constructor.
* @param SuperModuleInterface $module
* 通过构造器 注入依赖
*/
public function __construct(SuperModuleInterface $module)
{
$this->module = $module;
} public function show(array $target){ $this->module->activate($target);
}
} class PowerA implements SuperModuleInterface
{
public function activate(array $target)
{
echo '<pre>'. __METHOD__;
print_r(func_get_args());
}
} class PowerB implements SuperModuleInterface
{
public function activate(array $target)
{
echo '<pre>'. __METHOD__;
print_r(func_get_args());
}
} class Container
{
protected $binds; protected $instances; /**
* @param $abstract
* @param $concrete
* 把代词 绑定到容器里,为后续make
*/
public function bind($abstract, $concrete)
{
if ($concrete instanceof Closure) {
$this->binds[$abstract] = $concrete;
} else {
$this->instances[$abstract] = $concrete;
}
} /**
* @param $abstract
* @param array $parameters
* @return mixed
* 创建对象
*/
public function make($abstract, $parameters = [])
{
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
// 把容器对象$this,放到参数数组第一个元素。为call_user_func_array使用
array_unshift($parameters, $this); // 这里$this->binds[$abstract] 绑定的闭包函数, 执行函数参数是$parameters
return call_user_func_array($this->binds[$abstract], $parameters);
}
} // 创建一个容器(后面称作超级工厂)
$container = new Container; // 向该 超级工厂添加超能力模组的生产脚本
$container->bind('powerA', function($container) {
return new PowerA;
}); // 同上
$container->bind('powerB', function($container) {
return new PowerB;
}); // 向该 超级工厂添加超人的生产脚本
$container->bind('superman', function($container, $moduleName) {
return new Superman($container->make($moduleName));
}); echo "<pre>"; // 开始启动生产
$superman_1 = $container->make('superman', ['powerA']);
$superman_1->show(['a' => 1]); $superman_2 = $container->make('superman', ['powerB']);
$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. PC逆向之代码还原技术,第四讲汇编中减法的代码还原

    目录 PC逆向之代码还原技术,第四讲汇编中减法的代码还原 一丶汇编简介 二丶高级代码对应汇编观看. 1.代码还原解析: 三丶根据高级代码IDA反汇编的完整代码 四丶知识总结 PC逆向之代码还原技术,第 ...

  2. 做了2个多月的设计和编码,我梳理了Flutter动态化的方案对比及最佳实现

    背景 在端上为了提升App的灵活性, 快速解决万变的业务需求,开发者们探索了多种解决方案,如PhoneGap ,React Native ,Weex等,但在Flutter生态还没有好的解决方案.未来闲 ...

  3. 监控mysql

    Mysql服务器监控 管理MySql服务器属于应用程序监控范畴.这是因为绝大多数性能参数是有MySql软件产生的,而不属于主操作系统的一部分. 如当前所提到的,应该总是先监控基础操作系统,然后监控My ...

  4. Spring Boot 系列总目录

    一.Spring Boot 系列诞生原因 上学那会主要学的是 Java 和 .Net 两种语言,当时对于语言分类这事儿没什么概念,恰好在2009年毕业那会阴差阳错的先找到了 .Net 的工作,此后就开 ...

  5. Spring Boot 2.x(三):搭建开发环境(整合Spring Data JPA)

    为什么是JPA JPA虽然小众,但是足够优雅╮(╯_╰)╭,由于微服务的兴起,服务粒度的细化,多表联合的场景逐渐减少,更多的是一些简单的单表查询,而这正是JPA的强项所在.所以,以后的实战项目中我也会 ...

  6. 第25章 退出外部身份提供商 - Identity Server 4 中文文档(v1.0.0)

    当用户注销 IdentityServer并且他们使用外部身份提供程序登录时,可能会将其重定向到注销外部提供程序.并非所有外部提供商都支持注销,因为它取决于它们支持的协议和功能. 要检测是否必须将用户重 ...

  7. rand函数

    srand()用来初始化随机数种子,rand()用来产生随机数 srand(time()); while(t--){ printf("-> %d %d\n",rand(),r ...

  8. 重写(override)和重载(overload)的区别

    override(重写): 是进行基类中函数的重写,是面向对象的概念 重载(overload):是方法的名称相同,参数或参数类型不同,进行多次重载以适应不同的需要.overload 是面向对象的概念.

  9. Linux下批量添加用户

    添加和删除用户对每位Linux系统管理员都是轻而易举的事,比较棘手的是如果要添加几十个.上百个甚至上千个用户时,我们不太可能还使用useradd一个一个地添加, 必然要找一种简便的创建大量用户的方法. ...

  10. Java开发笔记(十三)利用关系运算符比较大小

    前面在<Java开发笔记(九)赋值运算符及其演化>中提到,Java编程中的等号“=”表示赋值操作,并非数学上的等式涵义.Java通过等式符号“==”表示左右两边相等,对应数学的等号“=”: ...