结论:

  • 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. Linux基础命令---smbpasswd管理samba密码

    smbpasswd smbpasswd指令可以用来修改samba用户的的密码,该指令不仅可以修改本地samba服务器的用户密码,还可以修改远程samba服务器的用户密码. 此命令的适用范围:RedHa ...

  2. Linux_spool命令

    spool的作用是什么? spool的作用可以用一句话来描述:在sqlplus中用来保存或打印查询结果. 参数指南 对于SPOOL数据的SQL,最好要自己定义格式,以方便程序直接导入,SQL语句如: ...

  3. MySQL索引及性能优化分析

    一.SQL性能下降的原因 查询语句问题,各种连接.子查询 索引失效(单值索引.复合索引) 服务器调优及各个参数设置(缓冲.线程池等) 二.索引 排好序的快速查找数据结构 1. 索引分类 单值索引 一个 ...

  4. sqlserver 各种判断是否存在(表、视图、函数、存储过程等)

    1.判断表是否存在 select * from sysobjects where id = object_id(表名) and OBJECTPROPERTY(id, N'IsUserTable') = ...

  5. Go语言核心36讲(Go语言实战与应用二十五)--学习笔记

    47 | 基于HTTP协议的网络服务 我们在上一篇文章中简单地讨论了网络编程和 socket,并由此提及了 Go 语言标准库中的syscall代码包和net代码包. 我还重点讲述了net.Dial函数 ...

  6. shell脚本 screen管理

    一.简介 源码地址 日期:2018/4/12 介绍:使用screen来启动程序,这个脚本可以管理screen 效果图: 二.使用 适用:centos6+ 语言:中文 注意:请先写一个脚本来启动java ...

  7. 资源的批量删除与替换(Project)

    <Project2016 企业项目管理实践>张会斌 董方好 编著 资源分配好以后,嗯,很满意! 可是!有人看了不满意,或者自己手贱分配错了,要改? 改就改呗,和分配有什么区别吗? 没有啊! ...

  8. JS获取url中query_str JavaScript RegExp 正则表达式基础详谈

    面我们举例一个URL,然后获得它的各个组成部分:http://i.cnblogs.com/EditPosts.aspx?opt=1 1.window.location.href(设置或获取整个 URL ...

  9. Linux 主从数据库

    主从数据库 主数据库的内容同步传输到附属数据库 客户访问附属数据库 这样做保证了数据库的稳定性 需要两台虚拟机 两边个虚拟机都要操作 配置hosts文件 进入/etc/hosts追加输入 192.16 ...

  10. SpringBoot整合log4j日志框架

    Spring Boot 2.x默认使用Logback日志框架,要使用 Log4j2必须先排除 Logback. 加入修改依赖 <dependency> <groupId>org ...