<?php

namespace App\Services;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis; class CacheDecorator
{
// 公司组织列表缓存key
const COMPANY_ORGANIZE_KEY = 'company_organize_%s'; private static function setStringCacheStorage($key, $expireTime, string $data)
{
if ($expireTime) {
Redis::setex($key, $expireTime, $data);
} else {
Redis::set($key, $data);
}
} /**
* 装饰器获取缓存数据
* @param $cacheKey 缓存key
* @param int $cacheTime 缓存时间
* @param object $obj 对象
* @param $method 缓存方法
* @param mixed ...$args 参数
* @return mixed
*/
public static function getStringCache($cacheKey, $expireTime, object $obj, $method, ...$args)
{
try {
$cacheData = Redis::get($cacheKey);
$cacheData = json_decode($cacheData, true);
if (empty($cacheData) || !isset($cacheData['org_data']) || empty($cacheData['org_data'])) {
$cacheData = [
'org_data' => call_user_func_array([$obj, $method], $args)
];
self::setStringCacheStorage($cacheKey, $expireTime, json_encode($cacheData, JSON_UNESCAPED_UNICODE));
Log::info('从数据库获取数据', [
'class' => get_class($obj),
'method' => $method,
'args' => $args,
]);
return $cacheData['org_data'];
} else {
Log::info('从缓存获取数据', [
'class' => get_class($obj),
'method' => $method,
'args' => $args,
]);
return $cacheData['org_data'];
}
} catch (\Exception $e) {
Log::error("redis缓存错误", [
'msg' => $e->getMessage(),
'line' => $e->getLine(),
'file' => $e->getFile(),
]);
}
Log::info('从数据库获取数据', [
'class' => get_class($obj),
'method' => $method,
'args' => $args,
]);
return call_user_func_array([$obj, $method], $args);
} /**
* 获取缓存key
* @param $format
* @param mixed ...$arg
* @return string
*/
public static function getCacheKey($format, ...$arg)
{
return sprintf($format, ...$arg);
}
}

调用

   public function listOrganize(AuthOrganizeService $authOrganizeService)
{
// before直接调用数据库
$list = $authOrganizeService->listCompanyOrganize(Auth::user()->company_id);
// after 直接使用缓存,但是listCompanyOrganize这个方法是没有进行任何的改动
$list = CacheDecorator::getStringCache(
CacheDecorator::getCacheKey(CacheDecorator::COMPANY_ORGANIZE_KEY),
100,
AuthOrganizeService,
'listCompanyOrganize',
1
);
$res = [
'list' => $list,
'total' => 1 //不分页
];
return $this->success($res);
}

php使用装饰模式无侵入式加缓存的更多相关文章

  1. Hook 无侵入式埋点(页面统计)

    一.技术原理 Method-Swizzling 黑魔法 方法交换(不懂的可以查) 二.页面统计 某盟页面统计SDK需要开发者在APP基类里实现ViewDidAppear和viewDidDisappea ...

  2. Spring Boot 无侵入式 实现RESTful API接口统一JSON格式返回

    前言 现在我们做项目基本上中大型项目都是选择前后端分离,前后端分离已经成了一个趋势了,所以总这样·我们就要和前端约定统一的api 接口返回json 格式, 这样我们需要封装一个统一通用全局 模版api ...

  3. 使用AOP思想无侵入式申请权限,解决组件化中权限问题(一)

    首先介绍AspectJx使用 https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx 在根项目的build.gradle ...

  4. Android平台免Root无侵入AOP框架Dexposed使用详解

    Dexposed是基于久负盛名的开源Xposed框架实现的一个Android平台上功能强大的无侵入式运行时AOP框架. Dexposed的AOP实现是完全非侵入式的,没有使用任何注解处理器,编织器或者 ...

  5. Android新技术学习——阿里巴巴免Root无侵入AOP框架Dexposed

    阿里巴巴无线事业部近期开源的Android平台下的无侵入运行期AOP框架Dexposed,该框架基于AOP思想,支持经典的AOP使用场景.可应用于日志记录,性能统计,安全控制.事务处理.异常处理等方面 ...

  6. 小议webpack下的AOP式无侵入注入

    说起来, 面向切面编程(AOP)自从诞生之日起,一直都是计算机科学领域十分热门的话题,但是很奇怪的是,在前端圈子里,探讨AOP的文章似乎并不是多,而且多数拘泥在给出理论,然后实现个片段的定式)难免陷入 ...

  7. MVC的验证(模型注解和非侵入式脚本的结合使用) .Net中初探Redis .net通过代码发送邮件 Log4net (Log for .net) 使用GDI技术创建ASP.NET验证码 Razor模板引擎 (RazorEngine) .Net程序员应该掌握的正则表达式

    MVC的验证(模型注解和非侵入式脚本的结合使用)   @HtmlHrlper方式创建的标签,会自动生成一些属性,其中一些属性就是关于验证 如图示例: 模型注解 通过模型注解后,MVC的验证,包括前台客 ...

  8. Android沉浸式(侵入式)标题栏(状态栏)Status(一)

     Android沉浸式(侵入式)标题栏(状态栏)Status(一) 现在越来越多的APP设计采用这种称之为沉浸式状态栏(Status)的设计,这种沉浸式状态栏又称之"侵入式"状 ...

  9. 无侵入方面编程-用HttpModule+SoapExtension监视页面执行参数(二)

    上一篇文章 "无侵入方面编程-用HttpModule+SoapExtension监视页面执行参数(一)"中,我们实现了监视每个页面的执行情况和调用WebService的简单信息. ...

随机推荐

  1. Tampermonkey油猴脚本管理插件-最强浏览器插件的安装使用全攻略

      对于接触过谷歌浏览器插件的“玩家”们来说,应该没有人没听说过Tampermonkey用户脚本管理器,也就是中文所说的“油猴”这个chrome插件了. 油猴号称全商店最强的浏览器插件绝非浪得虚名,一 ...

  2. idea的maven项目运行出错_java.io.FileNotFoundException: class path resource [spring/sprint-tx.xml] cannot be opened because it does not exist

    前提:idea  maven  ssm 错误信息如下: 严重: Exception sending context initialized event to listener instance of ...

  3. PHP内置常量,和可变变量,常量的定义

    关键常量 可变变量----变量名是变量的变量 常量的定义

  4. 【dmp文件还原到oralce数据库】

    1.数据库执行语句,创建一个用户并赋予权限 --创建用户CREATE USER test2 IDENTIFIED BY 123456 DEFAULT TABLESPACE USERS TEMPORAR ...

  5. 题解 【NOIP2014】解方程

    题面 解析 这题的数据看起来似乎特别吓人... 但实际上, 这题非常好想. 只需要模一个大质数就行了(我模的是1e9+7)(实测有效) 另外,a要用快读读入,再一边模Mod(因为实在太大了). 然后, ...

  6. 【Python之路】特别篇--Python反射

    反射 说反射之前先介绍一下__import__方法,这个和import导入模块的另一种方式 1. import commons 2. __import__('commons') 如果是多层导入: 1. ...

  7. 用go iris 写的一个网页版文件共享应用(webapp)

    主要演示文件拖拽上传或点击上传到不同的目录中,提供下载和删除功能. 目录结构: -main.go --share(用于分类存放上传文件的目录) --v(视图目录) ---share.html main ...

  8. webpack官方文档分析(三):Entry Points详解

    1.有很多种方法可以在webpack的配置中定义entry属性,为了解释为什么它对你有用,我们将展现有哪些方法可以配置entry属性. 2.单一条目语法 用法: entry: string|Array ...

  9. 灰度图像--图像分割 Sobel算子,Prewitt算子和Scharr算子平滑能力比较

    学习DIP第47天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan ,出于尊重文章作者的劳动,转载请标明出处!文章代码已托管,欢迎共同开发: https://g ...

  10. ValseWebninar 报告汇总

    ValseWebninar为计算机视觉.图像处理.模式识别与机器学习等研究领域内的华人青年学者提供深入学术交流的舞台. 20191218:基于视觉和常识的深度推理  主持人:    主讲人: 2019 ...