使用Spring Boot和自定义缓存注解优化应用性能

news2024/11/28 0:58:50

在现代应用开发中,缓存是提高系统性能和响应速度的关键技术之一。Spring Boot提供了强大的缓存支持,但有时我们需要更灵活的缓存控制。本文将介绍如何使用Spring Boot和自定义缓存注解来优化应用性能。

1. 为什么需要自定义缓存注解?

Spring Boot提供了@Cacheable@CachePut@CacheEvict等注解来管理缓存,但有时这些注解可能无法满足特定需求。例如,你可能需要更细粒度的缓存控制,或者希望在缓存中存储自定义数据结构。这时,自定义缓存注解就显得尤为重要。

2. 创建自定义缓存注解

首先,我们需要创建一个自定义的缓存注解。这个注解将允许我们指定缓存的键和过期时间。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CustomCacheable {

    /**
     *  缓存名称
     * @return
     */
    String key() default "";

    /**
     *  缓存条件
     * @return
     */
    String condition() default "";

    /**
     * 过期时间,单位秒
     */
    long expireTime() default 0;

}
3. 创建缓存切面

接下来,我们需要创建一个切面来处理自定义缓存注解。这个切面将拦截带有自定义缓存注解的方法,并根据注解的参数进行缓存操作。

@Aspect
@Component
public class CustomCacheAspect {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Around("@annotation(customCacheable)")
    public Object cache(ProceedingJoinPoint joinPoint, CustomCacheable customCacheable) throws Throwable {
        String key = customCacheable.key();
        long expireTime = customCacheable.expireTime();
        //获取方法名及参数值
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        // 构建缓存键
        key = key + ":" + methodName;
        if (args != null && args.length > 0) {
            for (Object arg : args) {
                key = key + ":" + arg;
            }
        }
        //获取方法参数名
//        String[] parameterNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
//        if (parameterNames != null) {
//            for (int i = 0; i < parameterNames.length; i++) {
//                key = key + ":" + args[i];
//            }
//        }

        // 尝试从缓存中获取数据
        Object cachedValue = redisTemplate.opsForValue().get(key);
        if (cachedValue != null) {
            return cachedValue;
        }

        // 如果缓存中没有数据,则执行方法并将结果存入缓存
        Object result = joinPoint.proceed();

        if(expireTime > 0){
            redisTemplate.opsForValue().set(key, result, expireTime, TimeUnit.SECONDS);
        }else{
            redisTemplate.opsForValue().set(key, result);
        }
        return result;
    }
}
4. 配置RedisTemplate

为了在切面中使用RedisTemplate,我们需要进行相应的配置。

:这里RedisConnectionFactory Bean 可不配,不过会有提示,看着不爽。

@Configuration
public class RedisConfig {
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(); // 或者使用JedisConnectionFactory等其他实现
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return template;
    }
}

 这里使用的依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.7.0</version>
        </dependency>
5. 使用自定义缓存注解

最后,我们可以在服务类中使用自定义缓存注解,这里使用的上一篇生成的代码测试一下。

    /**
     * 根据id查询
     */
    @GetMapping("/{id}")
    @CustomCacheable(key = "user")
    public  UserTest getById(@PathVariable Long id) {
        return userTestService.getById(id);
    }
6. 启用AOP支持

确保在你的Spring Boot应用中启用了AOP支持。你可以在application.properties中添加以下配置:

spring.aop.auto=true

或者在启动类上添加@EnableAspectJAutoProxy注解:

@SpringBootApplication
@EnableAspectJAutoProxy
public class AppStart  {

    public static void main(String[] args){
        SpringApplication.run(AppStart.class, args);
    }
}
7.测试

 

8.总结

通过自定义缓存注解和切面,我们可以在Spring Boot应用中实现更灵活的缓存控制。这不仅提高了应用的性能,还使得缓存管理更加便捷和高效。希望本文对你在Spring Boot应用中实现自定义缓存有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1903165.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CH12_函数和事件

第12章&#xff1a;Javascript的函数和事件 本章目标 函数的概念掌握常用的系统函数掌握类型转换掌握Javascript的常用事件 课程回顾 Javascript中的循环有那些&#xff1f;Javascript中的各个循环特点是什么&#xff1f;Javascript中的各个循环语法分别是什么&#xff1f;…

Android仿今日头条新闻(一)

新建一个侧边栏的文件&#xff0c;创建成功后直接运行。可以看到带滑动的侧边栏功能如图所示&#xff1a; 主体UI&#xff1a; 新闻UI的实现: 侧边栏&#xff1a; 更换一下颜色&#xff1a; 学习参考-浩宇开发

科研绘图系列:R语言两组数据散点分布图(scatter plot)

介绍 展示两组数据的散点分布图是一种图形化表示方法,用于显示两个变量之间的关系。在散点图中,每个点代表一个数据点,其x坐标对应于第一组数据的值,y坐标对应于第二组数据的值。以下是散点图可以展示的一些结果: 线性关系:如果两组数据之间存在线性关系,散点图将显示出…

【JVM系列】Full GC(完全垃圾回收)的原因及分析

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

IDA*——AcWing 180. 排书

IDA* 定义 IDA*&#xff08;Iterative Deepening A*&#xff09;是一种结合了深度优先搜索&#xff08;DFS&#xff09;的递归深度限制特性和A搜索的启发式估价函数的搜索算法。它主要用于解决启发式搜索问题&#xff0c;尤其是当搜索空间很大或者搜索成本不确定时。 IDA* 是…

分享大厂对于缓存操作的封装

hello&#xff0c;伙伴们好久不见&#xff0c;我是shigen。发现有两周没有更新我的文章了。也是因为最近比较忙&#xff0c;基本是993了。 缓存大家再熟悉不过了&#xff0c;几乎是现在任何系统的标配&#xff0c;并引申出来很多的问题&#xff1a;缓存穿透、缓存击穿、缓存雪崩…

markdown导入其它markdown文件

相应语法 [toc] # 测试不同功能 <p> 这是类似超链接的管理方式 </p>[链接测试0](./part0/uml_base.md)[链接测试1](./part1/math_base.md)---<p> 这是直接导入文件的管理方式 </p>import "./part0/uml_base.md"---import "./part1/mat…

arm64架构kvm情景分析 - type1型和type2型虚拟机管理器

内核版本&#xff1a;linux-v5.9 架构&#xff1a;arm64 1 type1型和type2虚拟机管理器 在arm64架构中&#xff0c;共有EL3到EL0四个异常级别&#xff0c;EL3异常级别最高。通常操作系统&#xff08;如linux&#xff09;运行在EL1&#xff0c;应用程序运行在EL0&#xff0c;EL…

S32DS S32 Design Studio for S32 Platform 3.5 代码显示行号与空白符

介绍 NXP S32DS&#xff0c;全称 S32 Design Studio&#xff0c;s32 系列芯片默认使用 S32 Design Studio for S32 Platform 作为 IDE 集成开发环境&#xff0c;当前版本 S32 Design Studio for S32 Platform 3.5&#xff0c;IDE 可以简称 s32DS 使用 S32DS&#xff0c;可以认…

python操作SQLite3数据库进行增删改查

python操作SQLite3数据库进行增删改查 1、创建SQLite3数据库 可以通过Navicat图形化软件来创建: 2、创建表 利用Navicat图形化软件来创建: 存储在 SQLite 数据库中的每个值(或是由数据库引擎所操作的值)都有一个以下的存储类型: NULL. 值是空值。 INTEGER. 值是有符…

JavaWeb开发基础7个Web术语解析

7个Web术语 Website: static vs dynamic HTTP HTTP Requests GET vs POST Servlet Container Server: Web vs Application Content Type Website: static vs dynamic 网站内容包括文本、图片、音频、视频&#xff0c;通过URL来访问。网站分为静态网站和动态网站。 静态网…

LLMs之gptpdf:gptpdf的简介、安装和使用方法、案例应用之详细攻略

LLMs之gptpdf&#xff1a;gptpdf的简介、安装和使用方法、案例应用之详细攻略 目录 gptpdf的简介 1、处理流程 第一步&#xff0c;使用 PyMuPDF 库&#xff0c;对 PDF 进行解析出所有非文本区域&#xff0c;并做好标记&#xff0c;比如: 第二步&#xff0c;使用视觉大模型&…

【数智化人物展】天云数据CEO雷涛:大模型连接数据库 为数智化提供高价值数据...

雷涛 本文由天云数据CEO雷涛投递并参与由数据猿联合上海大数据联盟共同推出的《2024中国数智化转型升级先锋人物》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 这几天&#xff0c;奥特曼讲SQL数据库和大模型结合起来会产生什么样的化学变化引起行业关注。为…

13.SQL注入-宽字节

SQL注入-宽字节 含义&#xff1a; MySQL是用的PHP语言&#xff0c;然后PHP有addslashes()等函数&#xff0c;这类函数会自动过滤 ’ ‘’ null 等这些敏感字符&#xff0c;将它们转义成’ ‘’ \null&#xff1b;然后宽字节字符集比如GBK它会自动把两个字节的字符识别为一个汉…

frp技术

说明&#xff1a;frp&#xff08;https://github.com/fatedier/frp&#xff09; 是一个专注于内网穿透的高性能的反向代理应用&#xff0c;支持 TCP、UDP、HTTP、HTTPS 等多种协议&#xff0c;且支持 P2P 通信。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露…

19.JWT

1►JWT博客推荐 阮老师讲得很好了&#xff0c;网址如下&#xff1a; http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html 2►ry是怎么践行JWT的呢&#xff1f; 问题一&#xff1a;不登录的时候有token吗&#xff1f; 答&#xff1a;没有&#xff0c;所…

中标麒麟 RAC 19c 部署(Openssh免密BUG解决方案)

部署环境&#xff1a; 主机一主机二host ip192.168.80.46192.168.80.47vip 192.168.80.48192.168.80.49private ip192.168.10.10192.168.10.11storage ip192.168.20.33192.168.20.34主机名rac19c1rac19c2 需要上传的软件包&#xff1a; 一.虚拟机配置 选择中标麒麟IOS文件&am…

关于 element-ui el-cascader 数据回显问题的解决方案

前言 这两天在使用 el-cascader 控件时&#xff0c;后端日期的数据如“2023-05-06”前端需要按照“年-月-日”的形式分割成三级联动&#xff0c;因为数据库保存的是完整的日期&#xff0c;前端数据回显时需要对后端返回的数据进行处理。 问题再现 联动下拉框的数据如下&#x…

昇思25天学习打卡营第十四天|Pix2Pix实现图像转换

训练营进入第十四天&#xff0c;今天学的内容是Pix2Pix图像转换&#xff0c;记录一下学习内容&#xff1a; Pix2Pix概述 Pix2Pix是基于条件生成对抗网络&#xff08;cGAN, Condition Generative Adversarial Networks &#xff09;实现的一种深度学习图像转换模型&#xff0c…

C语言 -- 扫雷游戏

C语言 – 扫雷游戏 游戏规则&#xff1a; 给定一个棋盘&#xff0c;玩家需要排查出所有隐藏的雷&#xff0c;也就是选择出所有不是雷的地方。 玩家选择位置&#xff0c;若此处有雷&#xff0c;玩家被炸死&#xff0c;游戏结束&#xff1b; 若此处无雷&#xff0c;此处提示周围一…