结论:

  • PHP中提供了反射类来解析类的结构;
  • 通过反射类可以获取到类的构造函数及其参数和依赖;
  • 给构造函数的参数递归设置默认值后,即可使用这些带默认值的参数通过 newInstanceArgs 实例化出类对象;
  • 在实例化的过程中,依赖的类也会被实例化,从而实现了依赖注入。

PHP中反射类的常用方法:

// 通过类名 Circle 实例化反射类
$reflectionClass = new reflectionClass(Circle::class);
// 获取类常量
$reflectionClass->getConstants();
// 获取类属性
$reflectionClass->getProperties();
// 获取类方法
$reflectionClass->getMethods();
// 获取类的构造函数
$constructor = $reflectionClass->getConstructor();
// 获取方法的参数
$parameters = $constructor->getParameters();
// 通过参数默认值数组实例化类创建对象
$class = $reflectionClass->newInstanceArgs($dependencies);

创建两个具有依赖关系的类:

class Point
{
public $x;
public $y; public function __construct($x = 0, $y = 0)
{
$this->x = $x;
$this->y = $y;
}
} class Circle
{
// 圆的半径
public $radius; // 圆心位置
public $center; const PI = 3.14; public function __construct(Point $point, $radius = 1)
{
$this->center = $point;
$this->radius = $radius;
} // 打印圆心位置的坐标
public function printCenter()
{
printf('圆心的位置是:(%d, %d)', $this->center->x, $this->center->y);
} //计算圆形的面积
public function area()
{
return 3.14 * pow($this->radius, 2);
}
}

创建两个方法:

make 方法负责解析类和构建类的对象;

getDependencies 负责依赖解析并初始化参数默认值;

//构建类的对象
function make($className)
{
try {
$reflectionClass = new ReflectionClass($className);
$constructor = $reflectionClass->getConstructor();
$parameters = $constructor->getParameters();
$dependencies = getDependencies($parameters); // 用指定的参数创建一个新的类实例
return $reflectionClass->newInstanceArgs($dependencies);
} catch (ReflectionException $e) {
throw new Exception("{$className} not found.");
}
} //依赖解析并初始化参数默认值
function getDependencies($parameters)
{
$dependencies = [];
// Circle 类的参数为 point 和 radius
// Point 类的参数为 x 和 y
foreach($parameters as $parameter) {
$dependency = $parameter->getClass();
// 如果参数不是类
if (is_null($dependency)) {
// 可选参数,有默认值
if($parameter->isDefaultValueAvailable()) {
$dependencies[] = $parameter->getDefaultValue();
}
// 必传参数暂时先给一个默认值
else {
$dependencies[] = '0';
}
}
// 如果参数是类
else {
// 递归进行依赖解析
$dependencies[] = make($parameter->getClass()->name);
}
} return $dependencies;
}

测试:

// 实例化对象
$circle = make('Circle');
// 调用对象的方法
$area = $circle->area();
var_dump($circle, $area);

过程说明:

make('Circle')
getDependencies(Point, int)
make('Point')
getDependencies(int, int)
new Point(int, int);
return Point;
new Circle(Point, int);
return Circle;

深入 Laravel 内核之 PHP 反射机制和依赖注入的更多相关文章

  1. Spring的反射机制和依赖注入

    我们知道,Spring中大量使用了反射机制,那么究竟是什么地方使用了呢? spring的一大核心概念是注入, 但是,这存在的一个前提就是类是由spring管理起来的. 反射是根据className生成 ...

  2. Spring进阶之路(1)-Spring核心机制:依赖注入/控制反转

    原文地址:http://blog.csdn.net/wangyang1354/article/details/50757098 我们经常会遇到这样一种情景,就是在我们开发项目的时候经常会在一个类中调用 ...

  3. 7 -- Spring的基本用法 -- 3... Spring 的核心机制 : 依赖注入

    7.3 Spring 的核心机制 : 依赖注入 Spring 框架的核心功能有两个. Spring容器作为超级大工厂,负责创建.管理所有的Java对象,这些Java对象被称为Bean. Spring容 ...

  4. (转)Spring读书笔记-----Spring核心机制:依赖注入

    Java应用(从applets的小范围到全套n层服务端企业应用)是一种典型的依赖型应用,它就是由一些互相适当地协作的对象构成的.因此,我们说这些对象间存在依赖关系.加入A组件调用了B组件的方法,我们就 ...

  5. Spring核心机制:依赖注入

    转载:http://www.cnblogs.com/chenssy/ Java应用(从applets的小范围到全套n层服务端企业应用)是一种典型的依赖型应用,它就是由一些互相适当地协作的对象构成的.因 ...

  6. Spring读书笔记-----Spring核心机制:依赖注入

    spring框架为我们提供了三种注入方式,分别是set注入,构造方法注入,接口注入.今天就和大家一起来学习一下 依赖注入的基本概念 依赖注入(Dependecy Injection),也称为IoC(I ...

  7. laravel服务容器(IOC控制反转,DI依赖注入),服务提供者,门脸模式

    laravel的核心思想: 服务容器: 容器:就是装东西的,laravel就是一个个的对象 放入:叫绑定 拿出:解析 使用容器的目的:这里面讲到的是IOC控制反转,主要是靠第三方来处理具体依赖关系的解 ...

  8. Spring学习-spring核心机制-IOC依赖注入

    转载自:http://www.cnblogs.com/chenssy/archive/2012/11/11/2765266.html 今天复习一下spring两大特性之一:IOC依赖注入,看了一下大佬 ...

  9. Spring-----3、Spring的核心机制(依赖注入)

    转载自:http://blog.csdn.net/hekewangzi/article/details/41345237

随机推荐

  1. OS开发之Objective-C与JavaScript的交互

    UIWebView是iOS最常用的SDK之一,它有一个stringByEvaluatingJavaScriptFromString方法可以将javascript嵌入页面中,通过这个方法我们可以在iOS ...

  2. 【Python】【Basic】【数据类型】运算符与深浅拷贝

    运算符   1.算数运算: 2.比较运算: 3.赋值运算: 4.逻辑运算: 5.成员运算: 三元运算 三元运算(三目运算),是对简单的条件语句的缩写. # 书写格式 result = 值1 if 条件 ...

  3. @Order注解使用

    注解@Order或者接口Ordered的作用是定义Spring IOC容器中Bean的执行顺序的优先级,而不是定义Bean的加载顺序,Bean的加载顺序不受@Order或Ordered接口的影响: @ ...

  4. Dubbo提供者的异步执行

    从前面"对提供者的异步调用"例子可以看出,消费者对提供者实现了异步调用,消费者线程的执行过程不再发生阻塞,但提供者对IO耗时操作仍采用的是同步调用,即IO操作仍会阻塞Dubbo的提 ...

  5. lucene中创建索引库

    package com.hope.lucene;import org.apache.commons.io.FileUtils;import org.apache.lucene.document.Doc ...

  6. eclipse.ini配置 vmargs 说明

    -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M 1. 各个参数的含义什么? 参数中-vmargs的意思是设置JVM参数, ...

  7. 如何使用pycharm克隆阿里云项目

    我们回到PyCharm刚打开时的界面,如图1-1所示:   点击"Check out from Version Control" => "Git",如图1 ...

  8. String 、StringBuffer、StringBuilder的区别

    String:字符串常量 StringBuffer:字符串变量:线程安全的 StringBuilder:字符串变量:线程非安全的 三者执行速度比较:StringBuilder >  String ...

  9. SpringCloud技术涵盖简介

    SpringCloud是微服务架构的集大成者,云计算最佳业务实践. 我们平常使用的Spring和他们的关系,对Spring,springboot , SpringCloud 的 概念区分,上图: Sp ...

  10. 原来这才是 Socket !

    关于对 Socket 的认识,大致分为下面几个主题,Socket 是什么,Socket 是如何创建的,Socket 是如何连接并收发数据的,Socket 套接字的删除等. Socket 是什么以及创建 ...