浅析easyswoole源码Di原理与实现 精选 原创 hgditren 2019-01-14 18:55:54 博主文章分类:PHP ©著作权 文章标签 php 单例模式 依赖注入 Di 容器 文章分类 软件研发 ©著作权归作者所有:来自51CTO博客作者hgditren的原创作品,请联系作者获取转载授权,否则将追究法律责任 依赖注入 简介:Dependency Injection 依赖注入 EasySwoole实现了简单版的IOC,使用 IOC 容器可以很方便的存储/获取资源,实现解耦。 使用依赖注入,最重要的一点好处就是有效的分离了对象和它所需要的外部资源,使得它们松散耦合,有利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。 在我们的日常开发中,创建对象的操作随处可见以至于对其十分熟悉的同时又感觉十分繁琐,每次需要对象都需要亲手将其new出来,甚至某些情况下由于坏编程习惯还会造成对象无法被回收,这是相当糟糕的。但更为严重的是,我们一直倡导的松耦合,少***原则,这种情况下变得一无是处。于是前辈们开始谋求改变这种编程陋习,考虑如何使用编码更加解耦合,由此而来的解决方案是面向接口的编程。 --摘自《easyswoole开发文档》 本文将解析并实现下列功能。 1、singleton模式的巧妙实现。 2、通过Di方式实现简单的容器,方便存取资源,从而达到解耦的目的。 代码实现 文件结构 \client.php 功能调用入口 \AbstractInterface\Singleton.php 单例抽象接口 \Lib\Redis.php redis服务类 \Service\Di.php 依赖注入实现简单Ioc容器 单例实现过程解读 client.php <?php /** * Created by PhpStorm. * User: zrj * Date: 19-1-14 * Time: 下午4:39 */ namespace App; define('APP_ROOT', dirname(__FILE__)); use Exception; use Yaconf; require_once APP_ROOT . '/Lib/Redis.php'; require_once APP_ROOT . '/Service/Di.php'; use App\Lib\Redis; use App\Service\Di; try { if (!Yaconf::has('easyswoole_api')) throw new Exception('项目配置ini文件不存在'); $redisCOnfig= Yaconf::get('easyswoole_api')['redis'] ?? []; if (empty($redisConfig)) throw new Exception('项目redis配置不存在'); $cOnfig= [ 'host' => (string)$redisConfig['host'] ?? '', 'port' => (int)$redisConfig['port'] ?? '', 'timeout' => (string)$redisConfig['timeout'] ?? '', 'password' => (string)$redisConfig['password'] ?? '', 'database' => (int)$redisConfig['database'] ?? '', ]; //直接访问 //Redis::getInstance($config)->set('hello', 'world'); //echo Redis::getInstance($config)->get('hello'); //Di::getInstance()->clear(); //注入容器 //--方法一、注入实例 //Di::getInstance()->set('redis', \App\Lib\Redis::getInstance($config)); //--方法二、容器内部实例化(支持单例模式) Di::getInstance()->set('redis', \App\Lib\Redis::class, $config); //通过容器获取实例 $redisInstance = Di::getInstance()->get('redis'); $redisInstance->set('dear', 'hui'); echo $redisInstance->get('hello') . PHP_EOL; echo $redisInstance->get('dear') . PHP_EOL; } catch (\Exception $e) { //throw $e; echo $e->getMessage(); } \AbstractInterface\Singleton.php 单例抽象接口 namespace App\AbstractInterface; #声明为特性 Trait Singleton { private static $instance; public static function getInstance(...$args) { if(!isset(self::$instance)){ //通过static静态绑定来new绑定的对象 self::$instance=new static(...$args); } return self::$instance; } } \Lib\Redis.php redis服务类 namespace App\Lib; require_once APP_ROOT . '/AbstractInterface/Singleton.php'; use App\AbstractInterface\Singleton; class Redis { //这里通过使用特性来扩展Redis类的能力 //借助Singleton中的getInstance来new本类,创建redis连接实例 //Redis::getInstance(...) use Singleton; private $cOnnectInstance= null; /** * Redis constructor. * @param array $redisConfig * @throws \Exception */ private function __construct(array $redisConfig) { try { //通过yaconf读取配置ini if (!extension_loaded('redis')) throw new \Exception('Redis extension is not install'); $this->cOnnectInstance= new \Redis(); $result = $this->connectInstance->connect($redisConfig['host'], $redisConfig['port'], $redisConfig['timeout']); $this->connectInstance->auth($redisConfig['password']); $this->connectInstance->select($redisConfig['database']); if ($result === false) throw new \Exception('Connect redis server fail'); } catch (\Exception $e) { throw $e; } } public function __call($name, $arguments) { return $this->connectInstance->$name(...$arguments); } } Redis类引入Singleton特性,轻松实现单例子。 //通过Redis::getInstance就能获取实例 Redis::getInstance($config)->set('hello', 'world'); echo Redis::getInstance($config)->get('hello'); 依赖注入的实现 \Service\Di.php 依赖注入实现简单Ioc容器 <?php /** * Created by PhpStorm. * User: zrj * Date: 19-1-14 * Time: 下午5:06 */ namespace App\Service; require_once APP_ROOT . '/AbstractInterface/Singleton.php'; require_once APP_ROOT . '/Lib/Redis.php'; use App\AbstractInterface\Singleton; //use App\Lib\Redis; class Di { use Singleton; private $cOntainer= []; //注入容器 public function set(string $key, $obj, array $arg = []): void { if (count($arg) == 1 && is_array($arg[0])) { $arg = $arg[0]; } $this->container[$key] = [ 'obj' => $obj, 'params' => $arg ]; } public function get(string $key) { if (!isset($this->container[$key])) return null; $result = $this->container[$key]; if (is_object($result['obj'])) { return $result['obj']; } elseif (is_callable($result['obj'])) {// 检测参数是否为合法的可调用结构(function,class method) return $result['obj']; } elseif (is_string($result['obj']) && class_exists($result['obj'])) { //通过反射方式获取实例化对象 $reflection = new \ReflectionClass($result['obj']); $cOnstructor= $reflection->getConstructor(); $instance = null; if ($constructor->isPublic()) {//直接实例化 $instance = $reflection->newInstanceArgs($result['params']); } elseif ($constructor->isPrivate()) {//支持单例模式 if ($reflection->hasMethod('getInstance')) { $instance = $result['obj']::getInstance($result['params']); } } $this->container[$key]['obj'] = $instance; return $instance; } else { return $result['obj']; } } public function clear(): void { $this->cOntainer= []; } public function delete($key): void { unset($this->container[$key]); } } 在client.php中使用Di的使用 //向容器中注入实例 //Di::getInstance()->set('redis', \App\Lib\Redis::getInstance($config)); Di::getInstance()->set('redis', \App\Lib\Redis::class, $config); //通过容器获取实例 $redisInstance = Di::getInstance()->get('redis'); $redisInstance->set('dear', 'hui'); echo $redisInstance->get('hello') . PHP_EOL; echo $redisInstance->get('dear') . PHP_EOL; 总结 本案例涉及知识点: 1.通过Yaconf扩展高效获取配置信息 2.static静态绑定、trait特性 3.singleton模式的实现 4.Di依赖注入 附:Yaconf配置文件(easyswoole_api.ini)格式 redis.host = '192.168.1.99' redis.port = 6379 redis.password = 'helloworld' redis.database = 12 redis.timeout = 3 赞 收藏 评论 分享 举报 上一篇:浅析laravel门面原理与实现 下一篇:[学习ES系列]-1.认识ElasticSearch及环境准备与服务搭建 提问和评论都可以,用心的回复会被更多人看到 评论 发布评论 全部评论 () 最热 最新 相关文章 Kubernetes API的设计思想与实现原理 前言本文主要会介绍笔者在学习Kubernetes API时所总结的知识点,其中会涉及到声明式API概念以及Kubernetes API对象的实现原理等方面的相关内容。笔者也会将自己的理解在文中进行阐述,这也算是在和大家交流心得的一个过程。若文中有错误的理解和概念,请大家及时纠正;吸纳大家的建议,对于我来说也是很重要的学习过程之一。目录4.自定义API对象1.声明式API1.1 声明 kubernetes CRD CR API UDP内网穿透和打洞原理与代码实现 1、众所周知,现在主流网络用的还是IPV4协议,理论上一共有2^32=43亿个地址,除去私有网段、网络ID、广播ID、保留网段、本地环回127.0.0.0网段、组播224.0.0.0网段、实际可用就是36.47亿个;全球的服务器、PC机、手机、物联网设备等需要通信的设备加起来远不止36.47亿,怎么才能尽可能让多的设备联网了?IPV6的地址有128位,理论上可以包含地球上每一粒沙子。但目前IPV4 服务器 IP 客户端 深度解析Nginx正向代理的原理与实现 前言Nginx是一个高性能的Web服务器和反向代理服务器,但它也可以用作正向代理服务器。本文将深入解析Nginx正向代理的原理和实现,并提供相关代码示例。1. 什么是正向代理正向代理是一种代理服务器的使用模式,客户端向代理服务器发送请求,代理服务器将请求转发给目标服务器,并将目标服务器的响应返回给客户端。客户端无法直接访问目标服务器,只能通过代理服务器进行访问。正向代理常用于以下情况:绕过网络限制 Nginx 服务器 正向代理 浅析Spring的IOC与DI IOC(控制反转):将对象的创建由代码本身转移到IOC容器,由主动创建对象的方式变成了被动注入对象,主从关系发生了改变,这就是我们所说的控制反转DI(依赖注入):依赖IOC容器注入某个对象所需要的外部资源IOC容器:实际上就是一个Map(key,value),Map里面存放的是各种对象;使用IOC容器的时候你不需要考虑对象是如何创建出来的,只需要配置好配置文件或注解即可,大大增加了项目的可维护性,降低了开发难度... spring 控制反转 可维护性 依赖注入 配置文件 GraphSage 算法原理介绍与源码浅析 GraphSage 算法原理介绍与源码浅析前言最近在做 Graph 相关的工作, 两年前做过一段时间, 想不到兜兜转转又回到 算法 深度学习 人工智能 图嵌入 伪代码 Future、FutureTask实现原理浅析(源码解读) Future、FutureTask实现原理浅析(源码解读)前言最近一直在看JUC下面的一些东西,发现很多东西都是以前用过,但是真是到原理层面自己还是很欠缺。刚好趁这段时间不太忙,回来了便一点点学习总结。前言最近一直在看JUC下面的一些东西,发现很多东西都是以前用过,但是真是到原理层面自己还是很欠缺。刚好趁这段时间不太忙,回来了便一点点学习总结。由于自己水平有限,可能存在大量漏洞和思考不周到的地方, Java 浅析laravel门面原理与实现 浅析门面(Facade)模式+容器 php facade 门面 容器 Netty实现原理浅析 Netty是JBoss出品的高效的Java NIO开发框架,关于其使用,可参考我的另一篇文章 netty使用初步。本文将主要分析Netty实现方面的东西,由于精力有限,本人并没有对其源码做了极细致的研 究。如果下面的内容有错误或不严谨的地方,也请指正和谅解。对于Netty使用者来说,Netty提供了几个典型的example,并有详尽的API doc和guide doc,本文的一些内容及图 Netty 数据 事件流 线程池 HashMap实现原理浅析 看了下JAVA里面有HashMap、Hashtable、HashSet三种hash集合的实现源码一、HashMap和Hashtable的区别1、两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全。Hashtable的实现方法里面都添加了synchronized关键字来确保线程同步,因此相对而言HashMap性能会高一些。我们平时使用时若无特殊需求建议使用... 【Java】 java spring 与easyswoole qps # 如何实现"java spring与easyswoole qps"## 一、整体流程以下是实现"java spring与easyswoole qps"的整体流程表格:| 步骤 | 内容 || ------ | ------ || 1 | 配置easyswoole服务器 || 2 | 编写Java Spring应用程序 || 3 | 实现QPS统计功能 || 4 | 验证QP java 服务器 spring HashMap 实现原理与源码分析 逐步来认识HashMap1、数组public class Array { /** * 删除 插入 慢 O(n) * 找到下标的查找 O(1) * java.util.ArrayList * @param args */ public static void main(String[] args) { Integer java EasySwoole easyswoole easy swoole 浅析 React / Vue 跨端渲染原理与实现 当下的前端同学对 React 与 Vue 的组件化开发想必不会陌生,RN 与 Weex 的跨界也常为我们所津津乐道。UI 框架在实现这样的跨端渲染时需要做哪些工作,其技术方案能否借鉴乃至应用到我们自己的项目中呢?这就是本文所希望分享的主题。概念简介什么是跨端渲染呢?这里的「端」其实并不局限在传统的 PC 端和移动端,而是抽象的 渲染层 (Renderer) 。渲染层并不局限在浏览器 DOM 和... vue react 小程序 mpvue 封装 浅析http的实现原理 http的实现原理http的实现原理其实就是数据在传输过程中的,基于TCP/IP 的通信协议,主要分为四步 java 客户端 web服务器 数据 Spring中的DI的实现原理 缘起中我们讲述了IOC容器的实现原理,我们知道IOC容器实际上就是把我们的Bean封装成一个BeanDefinition然后放入到一个map中,那么本篇主要讲述我们 spring中di的实现原理 sed 实例化 单例模式 依赖注入 SSM源码分析之Spring04-DI实现原理(基于XML注入) spring 依赖注入 属性值 实例化 ide NFM 网络介绍与源码浅析 NFM 网络介绍与源码浅析前言OK, 周末继续肝!!! 昨晚完成了 FNN 网络介绍与 深度学习 python tensorflow NFM CTR WebSocket 原理浅析与实现简单聊天 短轮询(Polling) 短轮询的实现思路就是浏览器端每隔几秒钟向服务器端发送 请求,服务端在收到请求后,不论是否有数据更新,都直接进行响应。在服务端响应完成,就会关闭这个 TCP 连接,代码实现也最简单,就是利用 XHR, 通过 setInterval 定时向后端发送请求,以获取最新的数 客户端 服务端 服务器 服务器端 数据 vue的双向绑定原理浅析与简单实现 很久之前看过vue的一些原理,对其中的双向绑定原理也有一定程度上的了解,只是最近才在项目上使用vue,这才决定好好了解下vue的实现原理,因此这里对vue的双向绑定原理进行浅析,并做一个简单的实现。 vue双向绑定的原理浅析 vue数据的双向绑定是通过数据劫持,并结合发布-订阅模式的方式来实现的。 数据 双向绑定 get方法 属性值 set方法 Spring IOC、DI、AOP原理和实现 (1)Spring IOC原理 IOC的意思是控件反转也就是由容器控制程序之间的关系,把控件权交给了外部容器,之前的写法,由程序代码直接操控,而现在控制权由应用代码中转到了外部容器,控制权的转移是... xml spring java ide 动态代理