结论:

  • 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. SpringBoot java配置类@Configuration 的两种写法

    首先在Springboot项目中,件一个java类,使用注解@Configuration  ,则这个类是SpringBoot bean的创建的配置文件类,,这种配置文件类有两种写法 1.使用包扫描 , ...

  2. myBatis批量添加实例

    <!-- 批量添加中转地数据 -->      <insert id="addBatch" parameterType="com.isoftstone. ...

  3. ERROR: Command errored out with exit status 1:安装pip3 install --user pyecharts==0.5.11失败问题总结

    一.前言:最近在学习pyecharts学习到Grid时候发现代码无法运行了,经过在网上查找资料说是pyecharts版本不适配了,之前的版本是 pip install pyecharts==0.1.9 ...

  4. 转:addChildViewController实现网易新闻首页切换

    本来只是打算介绍一下addChildViewController这个方法的,正好今天朋友去换工作面试问到网易新闻标签栏效果的实现,就结合它,用个小Demo实例介绍一下:(具体解释都写在了Demo里面的 ...

  5. Kerboros 认证

    转:Kerberos介绍(全)

  6. [BUUCTF]REVERSE——reverse2

    reverse2 附件 例行检查,64位目标 64位ida载入,首先shift+f12检索程序里的字符串 得到了"this is the right flag!" 的提示字符串,还 ...

  7. LET函数(Excel函数集团)

    LET函数,是个Office365新增函数,所以,还在用上古版本的童鞋请无视此篇哈~ 话说Excel中,有个自定义名称的功能,如下图,左右两个表分别自定义了"data1"和&quo ...

  8. 惊天大bug,一把螺丝刀,竟让我有家难回!

    1.回家路上看一地摊,螺丝刀2元一把,买了一个 2.芒格说:"如果你的工具只有一把锤子,你会认为任何问题都是钉子 " 那么当我手里有了一把起子,我看啥都是螺丝钉子. 出租屋里固定门 ...

  9. SQL Server日志恢复还原数据

    通过日志还原,首先要注意的是: 1,在数据库更新和删除之前有一个完整的备份. 2,在更新和删除之后,做一个日志备份. 3,该日志只能用于还原数据库备份和日志备份时间之间的数据. 下面看整个数据库备份和 ...

  10. docker部署验证码项目报错:at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)

    如果docker部署启动报错 java.lang.NullPointerException: nullat sun.awt.FontConfiguration.getVersion(FontConfi ...