深入 Laravel 内核之 PHP 反射机制和依赖注入
结论:
- 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 反射机制和依赖注入的更多相关文章
- Spring的反射机制和依赖注入
我们知道,Spring中大量使用了反射机制,那么究竟是什么地方使用了呢? spring的一大核心概念是注入, 但是,这存在的一个前提就是类是由spring管理起来的. 反射是根据className生成 ...
- Spring进阶之路(1)-Spring核心机制:依赖注入/控制反转
原文地址:http://blog.csdn.net/wangyang1354/article/details/50757098 我们经常会遇到这样一种情景,就是在我们开发项目的时候经常会在一个类中调用 ...
- 7 -- Spring的基本用法 -- 3... Spring 的核心机制 : 依赖注入
7.3 Spring 的核心机制 : 依赖注入 Spring 框架的核心功能有两个. Spring容器作为超级大工厂,负责创建.管理所有的Java对象,这些Java对象被称为Bean. Spring容 ...
- (转)Spring读书笔记-----Spring核心机制:依赖注入
Java应用(从applets的小范围到全套n层服务端企业应用)是一种典型的依赖型应用,它就是由一些互相适当地协作的对象构成的.因此,我们说这些对象间存在依赖关系.加入A组件调用了B组件的方法,我们就 ...
- Spring核心机制:依赖注入
转载:http://www.cnblogs.com/chenssy/ Java应用(从applets的小范围到全套n层服务端企业应用)是一种典型的依赖型应用,它就是由一些互相适当地协作的对象构成的.因 ...
- Spring读书笔记-----Spring核心机制:依赖注入
spring框架为我们提供了三种注入方式,分别是set注入,构造方法注入,接口注入.今天就和大家一起来学习一下 依赖注入的基本概念 依赖注入(Dependecy Injection),也称为IoC(I ...
- laravel服务容器(IOC控制反转,DI依赖注入),服务提供者,门脸模式
laravel的核心思想: 服务容器: 容器:就是装东西的,laravel就是一个个的对象 放入:叫绑定 拿出:解析 使用容器的目的:这里面讲到的是IOC控制反转,主要是靠第三方来处理具体依赖关系的解 ...
- Spring学习-spring核心机制-IOC依赖注入
转载自:http://www.cnblogs.com/chenssy/archive/2012/11/11/2765266.html 今天复习一下spring两大特性之一:IOC依赖注入,看了一下大佬 ...
- Spring-----3、Spring的核心机制(依赖注入)
转载自:http://blog.csdn.net/hekewangzi/article/details/41345237
随机推荐
- Synchronized深度解析
概览: 简介:作用.地位.不控制并发的影响 用法:对象锁和类锁 多线程访问同步方法的7种情况 性质:可重入.不可中断 原理:加解锁原理.可重入原理.可见性原理 缺陷:效率低.不够灵活.无法预判是否成功 ...
- docker容器使用loki收集日志
docker-compose安装loki套件(loki+promtail+grafana) loki进行日志聚合处理 类似elk中的es promtail是日志收集,类似elk中的logstash ...
- tableau绘制热力地图
一.右键国家地区和城市字段分别设置为地理角色-国家地区和城市 二.双击国家地区和城市添加到工作表 三.把订单id拖拽至标记卡的详细信息,标记改为密度显示,颜色设置为温度发散 四.最终整理结果如下图所示
- [HarekazeCTF2019]baby_rop
看到名字就想到了用rop来做这道题 老样子chescksec和file一下 可以看到是64位的程序开启了nx保护,把程序放到idax64里 可以看到有system和/bin/sh,/bin/sh无法跟 ...
- CF111A Petya and Inequiations 题解
Content 请找出一个由 \(n\) 个正整数组成的数列 \(\{a_1,a_2,\dots,a_n\}\),满足以下两种条件: \(\sum\limits_{i=1}^na_i^2\geqsla ...
- 私有化 : _x: 单前置下划线,私有化属性或方法;__xx:双前置下划线;__xx__:双前后下划线;属性property
私有化 xx: 公有变量 _x: 单前置下划线,私有化属性或方法,from somemodule import *禁止导入,类对象和子类可以访问 __xx:双前置下划线,避免与子类中的属性命名冲突,无 ...
- let, const用法以及与var的区别
let 定义变量; 作用域:全局作用域,块级作用域(简单说,是指一对大括号{}): 无预解析机制(简单说,变量需要在声明的位置后面使用): 不可以重复定义. const 定义常量: 作用域: 块级作用 ...
- c++设计模式概述之访问者
代码写的不够规范,目的是为了缩短篇幅,实际中请注意. 参看: http://c.biancheng.net/view/1397.html 1.概述 类比生活中的场景,购物商场中的商品.顾客.收营员.商 ...
- 【LeetCode】1133. Largest Unique Number 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 桶排序 日期 题目地址:https://leetcod ...
- 【LeetCode】551. Student Attendance Record I 解题报告(Java & Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 正则表达式 统计 日期 题目地址:https://l ...