java对象作为key值的实例分析
发表于:2025-11-09 作者:千家信息网编辑
千家信息网最后更新 2025年11月09日,这篇文章给大家介绍java对象作为key值的实例分析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1.实现方式说明下面在---- 手写redis @ Cacheable注解支持过
千家信息网最后更新 2025年11月09日java对象作为key值的实例分析
这篇文章给大家介绍java对象作为key值的实例分析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
1.实现方式说明
下面在---- 手写redis @ Cacheable注解支持过期时间设置 的基础之上进行扩展。
1.1问题说明
@ Cacheable(key = "'leader'+#p0 +#p1 +#p2" )一般用法,#p0表示方法的第一个参数,#p1表示第二个参数,以此类推。
目前方法的第一个参数为Java的对象,但是原注解只支持Java的的基本数据类型。
1.2实现步骤
1.在原注解中加入新的参数,
objectIndexArray表示哪几个角标参数(从0开始)为java对象,objectFieldArray表示对应位置该对象的字段值作为key
2.如何获取参数的对象以及该字段的值
使用的java的反射,拼接get方法获取该字段值。
2.源代码
修改java注解@ExtCacheable,本文中使用@NewCacheable
package com.huajie.annotation; import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target; @Target({ ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)public @interface NewCacheable { String key() default ""; int[] objectIndexArray(); String[] objectFieldArray(); int expireTime() default 1800;//30分钟 }SpringAop切面NewCacheableAspect
获取AOP整体流程没有任何变化
主要是关键值获取的方式,发生了变化

使用Java的反射技术

完整代码如下:
package com.huajie.aspect; import com.huajie.annotation.NewCacheable;import com.huajie.utils.RedisUtil;import com.huajie.utils.StringUtil;import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List; /** * redis缓存处理 不适用与内部方法调用(this.)或者private */@Component@Aspect@Slf4jpublic class NewCacheableAspect { @Autowired private RedisUtil redisUtil; @Pointcut("@annotation(com.huajie.annotation.NewCacheable)") public void annotationPointcut() { } @Around("annotationPointcut()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { // 获得当前访问的class Class> className = joinPoint.getTarget().getClass(); // 获得访问的方法名 String methodName = joinPoint.getSignature().getName(); // 得到方法的参数的类型 Class>[] argClass = ((MethodSignature) joinPoint.getSignature()).getParameterTypes(); Object[] args = joinPoint.getArgs(); String key = ""; int expireTime = 3600; try { // 得到访问的方法对象 Method method = className.getMethod(methodName, argClass); method.setAccessible(true); // 判断是否存在@ExtCacheable注解 if (method.isAnnotationPresent(NewCacheable.class)) { NewCacheable annotation = method.getAnnotation(NewCacheable.class); key = getRedisKey(args, annotation); expireTime = getExpireTime(annotation); } } catch (Exception e) { throw new RuntimeException("redis缓存注解参数异常", e); } log.info(key); boolean hasKey = redisUtil.hasKey(key); if (hasKey) { return redisUtil.get(key); } else { Object res = joinPoint.proceed(); redisUtil.set(key, res); redisUtil.expire(key, expireTime); return res; } } private int getExpireTime(NewCacheable annotation) { return annotation.expireTime(); } private String getRedisKey(Object[] args, NewCacheable annotation) throws Exception{ String primalKey = annotation.key(); // 获取#p0...集合 List keyList = getKeyParsList(primalKey); for (String keyName : keyList) { int keyIndex = Integer.parseInt(keyName.toLowerCase().replace("#p", "")); Object parValue = getParValue(annotation, keyIndex, args); primalKey = primalKey.replace(keyName, String.valueOf(parValue)); } return primalKey.replace("+", "").replace("'", ""); } private Object getParValue(NewCacheable annotation, int keyIndex, Object[] args) throws Exception{ int[] objectIndexArray = annotation.objectIndexArray(); String[] objectFieldArray = annotation.objectFieldArray(); if (existsObject(keyIndex, objectIndexArray)) { return getParValueByObject(args, keyIndex, objectFieldArray); } else { return args[keyIndex]; } } private Object getParValueByObject(Object[] args, int keyIndex, String[] objectFieldArray) throws Exception { Class cls = args[keyIndex].getClass(); Method method; if(objectFieldArray!=null&&objectFieldArray.length>=keyIndex){ method = cls.getMethod("get" + StringUtil.firstCharToUpperCase(objectFieldArray[keyIndex])); }else{ method = cls.getMethod("get" + StringUtil.firstCharToUpperCase(cls.getFields()[0].getName())); } method.setAccessible(true); log.info(method.getName()); return method.invoke(args[keyIndex]); } private boolean existsObject(int keyIndex, int[] objectIndexArray) { if (objectIndexArray == null || objectIndexArray.length <= 0) { return false; } for (int i = 0; i < objectIndexArray.length; i++) { if (keyIndex == objectIndexArray[i]) { return true; } } return false; } // 获取key中#p0中的参数名称 private static List getKeyParsList(String key) { List ListPar = new ArrayList(); if (key.indexOf("#") >= 0) { int plusIndex = key.substring(key.indexOf("#")).indexOf("+"); int indexNext = 0; String parName = ""; int indexPre = key.indexOf("#"); if (plusIndex > 0) { indexNext = key.indexOf("#") + key.substring(key.indexOf("#")).indexOf("+"); parName = key.substring(indexPre, indexNext); } else { parName = key.substring(indexPre); } ListPar.add(parName.trim()); key = key.substring(indexNext + 1); if (key.indexOf("#") >= 0) { ListPar.addAll(getKeyParsList(key)); } } return ListPar; } } 3.测试
业务模块使用方法controller
@RequestMapping("queryQuotaTreeData") @ResponseBody public List getTreeData() { QuotaManage quotaManage = new QuotaManage(); quotaManage.setQuotaName("测试22222"); List list = this.quotaManageService.queryQuotaTreeData(quotaManage); return list; } 实现层objectIndexArray中的{0}表示第0个参数,objectFieldArray中的"quotaName"表示对应对象中的字段名称
@Override @NewCacheable(key="test+#p0",objectIndexArray = {0},objectFieldArray = {"quotaName"}) public List queryQuotaTreeData(QuotaManage quotaManage) { List returnNodesList = new ArrayList(); List nodeList = this.mapper.queryQuotaTreeData(); returnNodesList = treeUtils.getParentList(nodeList); log.info(nodeList.size()+""); return returnNodesList; } 控制台截图拼接的get方法名称和获取的字段值
Redis的截图
关于java对象作为key值的实例分析就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
参数
方法
对象
注解
字段
名称
实例
实例分析
分析
内容
截图
方式
更多
类型
缓存
反射
变化
帮助
支持
测试
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
中国版本图书馆数据库查询
上海银联软件开发部门
魔兽世界服务器上线刷新
安徽软件开发收费标准
软件开发笔记本要求
网络安全手抄报一年级内容少
黑魂2服务器怎么用
软件开发中挡板是啥
千锋教育数据库百度网盘链接
政法干警学习网络安全
广州飞客科技互联网公司
国企信息数据库
怎么将流写入数据库
旅游软件开发计划书
服务器主板多次开机
mssql 数据库比对
胜讯网络技术有限公司
湖北兰新网络技术有限公司招标
国家网络安全日观后感
沈明峰 网络安全
上海银联软件开发部门
地震资料处理软件开发招聘
wost数据库
我的世界服务器如何显示小地图
ftp 入侵服务器
苏州软件开发+100人+于
微信小程序多层数据库
北京网络安全维护
企业软件开发技术说明
idc服务器运维管理系统批发