PHP类的反射和依赖注入
/**
* Class Point
*/
class Point
{
public $x;
public $y; /**
* Point constructor.
* @param int $x horizontal value of point's coordinate
* @param int $y vertical value of point's coordinate
*/
public function __construct($x = , $y = )
{
$this->x = $x;
$this->y = $y;
}
}
class Circle
{
/**
* @var int
*/
public $radius;//半径 /**
* @var Point
*/
public $center;//圆心点 const PI = 3.14; public function __construct(Point $point, $radius = )
{
$this->center = $point;
$this->radius = $radius;
} //打印圆点的坐标
public function printCenter()
{
printf('center coordinate is (%d, %d)', $this->center->x, $this->center->y);
} //计算圆形的面积
public function area()
{
return 3.14 * pow($this->radius, );
}
}
ReflectionClass
下面我们通过反射来对Circle这个类进行反向工程。
把Circle类的名字传递给reflectionClass来实例化一个ReflectionClass类的对象。
$reflectionClass = new reflectionClass(Circle::class);
//返回值如下
object(ReflectionClass)#1 (1) {
["name"]=>
string(6) "Circle"
}
反射出类的常量
$reflectionClass->getConstants();
返回一个由常量名称和值构成的关联数组
array(1) {
["PI"]=>
float(3.14)
}
通过反射获取属性
$reflectionClass->getProperties();
返回一个由ReflectionProperty对象构成的数组
array() {
[]=>
object(ReflectionProperty)# () {
["name"]=>
string() "radius"
["class"]=>
string() "Circle"
}
[]=>
object(ReflectionProperty)# () {
["name"]=>
string() "center"
["class"]=>
string() "Circle"
}
}
反射出类中定义的方法
$reflectionClass->getMethods();
返回ReflectionMethod对象构成的数组
array(3) {
[0]=>
object(ReflectionMethod)#2 (2) {
["name"]=>
string(11) "__construct"
["class"]=>
string(6) "Circle"
}
[1]=>
object(ReflectionMethod)#3 (2) {
["name"]=>
string(11) "printCenter"
["class"]=>
string(6) "Circle"
}
[2]=>
object(ReflectionMethod)#4 (2) {
["name"]=>
string(4) "area"
["class"]=>
string(6) "Circle"
}
}
我们还可以通过getConstructor()来单独获取类的构造方法,其返回值为一个ReflectionMethod对象。
$constructor = $reflectionClass->getConstructor();
反射出方法的参数
$parameters = $constructor->getParameters();
其返回值为ReflectionParameter对象构成的数组。
array(2) {
[0]=>
object(ReflectionParameter)#3 (1) {
["name"]=>
string(5) "point"
}
[1]=>
object(ReflectionParameter)#4 (1) {
["name"]=>
string(6) "radius"
}
}
依赖注入
好了接下来我们编写一个名为make的函数,传递类名称给make函数返回类的对象,在make里它会帮我们注入类的依赖,即在本例中帮我们注入Point对象给Circle类的构造方法。
//构建类的对象
function make($className)
{
$reflectionClass = new ReflectionClass($className);
$constructor = $reflectionClass->getConstructor();
$parameters = $constructor->getParameters();
$dependencies = getDependencies($parameters); return $reflectionClass->newInstanceArgs($dependencies);
} //依赖解析
function getDependencies($parameters)
{
$dependencies = [];
foreach($parameters as $parameter) {
$dependency = $parameter->getClass();
if (is_null($dependency)) {
if($parameter->isDefaultValueAvailable()) {
$dependencies[] = $parameter->getDefaultValue();
} else {
//不是可选参数的为了简单直接赋值为字符串0
//针对构造方法的必须参数这个情况
//laravel是通过service provider注册closure到IocContainer,
//在closure里可以通过return new Class($param1, $param2)来返回类的实例
//然后在make时回调这个closure即可解析出对象
//具体细节我会在另一篇文章里面描述
$dependencies[] = '';
}
} else {
//递归解析出依赖类的对象
$dependencies[] = make($parameter->getClass()->name);
}
} return $dependencies;
}
定义好make方法后我们通过它来帮我们实例化Circle类的对象:
$circle = make('Circle');
$area = $circle->area();
var_dump($area);
$areas = $circle->printCenter();
var_dump($areas);
float(3.14)
center coordinate is (0, 0)
PHP类的反射和依赖注入的更多相关文章
- ThinkPHP6源码:从Http类的实例化看依赖注入是如何实现的
ThinkPHP 6 从原先的 App 类中分离出 Http 类,负责应用的初始化和调度等功能,而 App 类则专注于容器的管理,符合单一职责原则. 以下源码分析,我们可以从 App,Http 类的实 ...
- 添加EF上下文对象,添加接口、实现类以及无处不在的依赖注入(DI)
添加EF上下文对象,添加接口.实现类以及无处不在的依赖注入(DI) 目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 上一章,我们介绍了安装和新建控制器.视图,这一章我们来创建 ...
- laravel中如何利用反射实现依赖注入
依赖注入 在一个类中经常会依赖于其他的对象,先看一下经典的写法 class Foo { public $bar; public function __construct() { $this->b ...
- 【无私分享:ASP.NET CORE 项目实战(第二章)】添加EF上下文对象,添加接口、实现类以及无处不在的依赖注入(DI)
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 上一章,我们介绍了安装和新建控制器.视图,这一章我们来创建个数据模型,并且添加接口和实现类. 添加EF上下文对象 按照我们以前 ...
- 第四节:配置的读取、StartUp类、内置依赖注入和扩展改造
一. 配置的读取 在Asp.Net Core中,有一个 appsettings.json 文件,用于存储相应的配置信息,读取的时,要通过构造函数注入:IConfiguration Configurat ...
- Java反射及依赖注入简单模拟
一.编写Dao类 ? 1 2 3 4 5 6 7 8 9 10 11 package cn.com.songjy.annotation; import java.util.Date; publ ...
- 【Java】利用注解和反射实现一个"低配版"的依赖注入
在Spring中,我们可以通过 @Autowired注解的方式为一个方法中注入参数,那么这种方法背后到底发生了什么呢,这篇文章将讲述如何用Java的注解和反射实现一个“低配版”的依赖注入. 下面是我们 ...
- DI容器Ninject在管理接口和实现、基类和派生类并实现依赖注入方面的实例
当一个类依赖于另一个具体类的时候,这样很容易形成两者间的"强耦合"关系.我们通常根据具体类抽象出一个接口,然后让类来依赖这个接口,这样就形成了"松耦合"关系,有 ...
- 转 Autofac怎么依赖注入ASP.NET MVC5类的静态方法
之前我有介绍过怎么在ASP.NET mvc5中实现的Controller的依赖注入.一般是通过Contrller的构造函数的参数或者属性来注入,但是这有一个共同点就是调用这个类的方法一般都是实例方法, ...
随机推荐
- mysql知识点汇总
1. 数据库的安装 2. 数据库设计需要注意什么 3. SQL语句优化 4. 怎样处理慢查询? 5. 怎样更好的利用数据库索引? 6. 事务隔离级别有哪些?怎么实现的? 7. 数据库锁有哪些? 8. ...
- Vue入门:Vue环境安装
安装环境 操作系统:Windows 10 64位 安装Node.js 1. 下载系统对应版本安装包 下载地址:https://nodejs.org/en/download/ 2. 安装 除安装地址外其 ...
- sourceTree 代码冲突解决
1.代码提交,有冲突 2. 拉取未同步的代码,勾选用衍合代替合并. 3. 在工作副本,未提交代码显示 4. 冲突代码解决 5. sourcetree页面
- linux 定时计划任务设置
安装 crontabs服务并设置开机自启 yum install crontabs systemctl enable crond (设为开机启动) systemctl start crond(启动cr ...
- spring boot使用mongodb时,xxxRepository不能Autowired的问题
默认情况下,当继承MongoRepository的CRUD在@SpringBootApplication的子包下时,xxxRepository是能够自动被扫描和创建代理的.但是如果不在默认路径下,就无 ...
- Angular 中的数据交互(get jsonp post)
Angular get 请求数据 Angular5.x 以后 get.post 和和服务器交互使用的是 HttpClientModule 模块. import {HttpClientModule} f ...
- COMP 321
COMP 321April 24, 2019Questions on this exam may refer to the textbook as well as to the manual page ...
- mongodb副本集基于centos7部署
安装mongodb,基于端口的安装三个节点 下载安装MongoDB安装包 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel ...
- unity 根据平板 或者 手机 确立横竖屏
/* ######### ############ ############# ## ########### ### ###### ##### ### ####### #### ### ####### ...
- Page.Cache
https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.page.cache?view=netframework-4.8 Gets the ...