SpringDI方式及Redis应用场景的分享

1、为什么Spring和IDEA 都不推荐使用 @Autowired 注解

        大家在使用IDEA开发的时候有没有注意到过一个提示,在字段上使用Spring的依赖注入注解@Autowired后会出现如下警告Field injection is not recommended (字段注入是不被推荐的)但是使用@Resource却不会出现此提示,那这是为什么呢??

        我们都知道Spring常见的DI方式:

  1. 构造器注入:利用构造方法的参数注入依赖
  2. Setter注入:调用Setter的方法注入依赖
  3. 字段注入:在字段上使用@Autowired/Resource注解

        @Autowired VS @Resource

        事实上,他们的基本功能都是通过注解实现依赖注入,只不过@AutowiredSpring定义的,而@ResourceJSR-250定义的。大致功能基本相同,但是还有一些细节不同:

  1. 依赖识别方式:@Autowired默认是byType,可以使用@Qualifier指定Name,@Resource默认ByName,如果找不到则ByType
  2. 适用对象:@Autowired可以对构造器、方法、参数、字段使用,@Resource只能对方法、字段使用
  3. 提供方:@Autowired是Spring提供的,@Resource是JSR-250提供的

        各种DI方式的优缺点

        参考Spring官方文档,建议了如下的使用场景:

  1. 构造器注入:强依赖性(即必须使用此依赖),不变性(各依赖不会经常变动)
  2. Setter注入:可选(没有此依赖也可以工作),可变(依赖会经常变动)
  3. Field注入:大多数情况下尽量少使用字段注入,一定要使用的话,@Resource相对@Autowired对IoC容器的耦合更低

        Field注入的缺点

  1. 不能像构造器那样注入不可变的对象
  2. 依赖对外部不可见,外界可以看到构造器和setter,但无法看到私有字段,自然无法了解所需依赖
  3. 会导致组件与IoC容器紧耦合(这是最重要的原因,离开了IoC容器去使用组件,在注入依赖时就会十分困难)
  4. 导致单元测试也必须使用IoC容器,原因同上
  5. 依赖过多时不够明显,比如我需要10个依赖,用构造器注入就会显得庞大,这时候应该考虑一下此组件是不是违反了单一职责原则

        为什么IDEA只对@Autowired警告

        Field注入虽然有很多缺点,但它的好处也不可忽略:那就是太方便了。使用构造器或者setter注入需要写更多业务无关的代码,十分麻烦,而字段注入大幅简化了它们。并且绝大多数情况下业务代码和框架就是强绑定的,完全松耦合只是一件理想上的事,牺牲了敏捷度去过度追求松耦合反而得不偿失。

        那么问题来了,为什么IDEA只对@Autowired警告,却对@Resource视而不见呢?

        @AutowiredSpring提供的,它是特定IoC提供的特定注解,这就导致了应用与框架的强绑定,一旦换用了其他的IoC框架,是不能够支持注入的。而@ResourceJSR-250提供的,它是Java标准,我们使用的IoC容器应当去兼容它,这样即使更换容器,也可以正常工作。

2、工作中常用Redis的十种场景

Redis是一种优秀的基于键值型NoSql数据库非关系型

这里有两个关键字:

其中键值型,是指Redis中存储的数据都是以key、value对的形式存储,而value的形式多种多样,可以是字符串、数值、甚至json

而NoSql则是相对于传统关系型数据库而言,有很大差异的一种数据库。

Redis的优点:

  1. 键值(key-value)型,value支持多种不同数据结构,功能丰富
  2. 单线程,每个命令具备原子性
  3. 低延迟,速度快(基于内存、IO多路复用、良好的编码)
  4. 支持数据持久化
  5. 支持主从集群、分片集群
  6. 支持多语言客户端

Redis在工作中的应用列举:

1、计数器

在很多网站首页,会有一些统计首页访问次数的需求,访问次数只有一个字段,如果存到关系型数据库中,最后做汇总会很麻烦。该业务场景可以使用Redis,定义一个key,例如:WEBSITE_VISITS_NUM。

在Redis里有命令incr,实现给value值加1操作:

incr WEBSITE_VISITS_NUM

当然如果你想一次加的值大于1,可以用incrby命令,例如:

Incrby WEBSITE_VISITS_NUM 10  一次加10。

2、分布式锁(单线程,数据安全)

最常见应用场景之一,相对于例如Zookeeper分布式锁,Redis的分布式锁,有更好的性能。

代码奉上:

@Api(tags = "Redis")
@RestController
@RequestMapping("/testRedis")
@Slf4j
public class TestRedisController {private static final ThreadFactory THREAD_FACTORY = new ThreadFactoryBuilder().setNamePrefix("shouhu-").setDaemon(true).build();private static final ScheduledExecutorService daemonPool = Executors.newScheduledThreadPool(5,THREAD_FACTORY);@Resourceprivate RedisTemplate<String ,Object> redisTemplate;@GetMapping("/testSetNX")@ApiOperation("SETNX")public ResultVO<Object> testSetNX(@RequestParam Long goodsId){String key = "lock_" + goodsId;String value = UUID.randomUUID().toString();ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();ScheduledFuture<?> scheduledFuture = null;try {// 加锁Boolean ifAbsent = valueOperations.setIfAbsent(key, value, 30, TimeUnit.SECONDS);log.info("加锁{}返回值:{}",key,ifAbsent);if ((null==ifAbsent) || (!ifAbsent)){log.info("加锁失败,请稍后重试!");return ResultUtils.error("加锁失败,请稍后重试!");}// 模拟看门狗逻辑AtomicInteger count = new AtomicInteger(1);scheduledFuture = daemonPool.scheduleWithFixedDelay(() -> {log.info("看门狗第:{}次执行开始", count.get());Object cache = redisTemplate.opsForValue().get(key);if (Objects.nonNull(cache) && (value.equals(cache.toString()))) {// 重新设置有效时间为30秒redisTemplate.expire(key, 30, TimeUnit.SECONDS);log.info("看门狗第:{}次执行结束,有效时间为:{}", count.get(), redisTemplate.getExpire(key));}else {log.info("看门狗执行第:{}次异常:key:{} 期望值:{} 实际值:{}",count.get(), key, value, cache);}count.incrementAndGet();}, 10, 10, TimeUnit.SECONDS);// 执行业务逻辑TimeUnit.SECONDS.sleep(5);log.info("业务逻辑执行结束");}catch (Exception e){log.error("testSetNX exception:",e);return ResultUtils.sysError();}finally {// 释放锁,判断是否是当前线程加的锁String delVal = valueOperations.get(key).toString();if (value.equals(delVal)){Boolean delete = redisTemplate.delete(key);log.info("释放{}锁结果:{}",key,delete);// 关闭看门狗线程if (Objects.nonNull(scheduledFuture)){boolean cancel = scheduledFuture.cancel(true);log.info("关闭看门狗结果:{}",cancel);}}else {log.info("不予释放,key:{} value:{} delVal:{}",key,value,delVal);}}return ResultUtils.success("success");}}
3、缓存加速

这也是工作中非常常用的一种,例如:大宗采购项目中,如果查询检斤化验单数据,先从Redis缓存中查询,如果缓存里存在,则直接拿出数据进行计算,如果不存在,则再去检斤进行查询数据,将数据保存到缓存里。

对于用户而言,下面的流程图也是常见的:

4、交集差集(Redis的无序集合应用)

例如:共同好友、推荐好友功能,我们可以使用到Redis的无序集合,命令如下:

sadd key val val --->添加
sinter key1 key2 ---->交集
sdiff key1 key2 ----->差集
5、排行榜(Redis的有序集合应用)

很多网站有排行榜的功能,比如:商城中有商品销量的排行榜,游戏网站有玩家获得积分的排行榜。这种情况下,我们可以使用Sorted Set保存排行榜的数据。使用ZADD可以添加排行榜的数据,使用ZRANGE可以获取排行榜的数据。

ZADD rank:score 100 "张三"
ZADD rank:score 90 "李四"
ZADD rank:score 80 "王五"
ZRANGE rank:score 0 -1 WITHSCORES

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用 Redis 实现延迟队列?

延迟队列是一种常见的消息队列模式&#xff0c;用于处理需要延迟执行的任务或消息。Redis 是一种快速、开源的键值对存储数据库&#xff0c;具有高性能、持久性和丰富的数据结构&#xff0c;因此很适合用于实现延迟队列。在这篇文章中&#xff0c;我们将详细讨论如何使用 Redis…

在虚拟环境中找到Qt Designer

Pyqt5中找到Qt Designer 安装Pyqt5和Qt Designer: pip install pyqt5-tools 假设Python的虚拟环境名为:d2l &#xff0c;虚拟环境在d2l文件夹中 D:\Software\d2l\Lib\site-packages\qt5_applications\Qt\bin 双击Qt designer启动 Pyside2中找到Qt Designer 安装pyside2 …

【牛客网】排列计算

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 如果直接涂色来计算单点权重&#xff0c;2e5*2e5必然超时。 所以用差分进行优化。 3. 代码实现 #include<bits/stdc.h> using name…

面试经典算法题之双指针专题

力扣经典面试题之双指针 ( 每天更新, 每天一题 ) 文章目录 力扣经典面试题之双指针 ( 每天更新, 每天一题 )验证回文串收获 392. 判断子序列167. 两数之和 - 输入有序数组11.盛开多水的容器 验证回文串 思路 一: 筛选 双指针验证 class Solution { public:bool isPalindrome(s…

Flutter笔记:谈Material状态属性-为什么FlatButton等旧版按钮就废弃了

Flutter笔记 谈Material状态属性-为什么FlatButton等旧版按钮就废弃了 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this artic…

机器学习:深入解析SVM的核心概念【四、软间隔与正则化】

软间隔与正则化 问题一&#xff1a;优化目标函数是如何得到的&#xff1f;得到的过程是怎样的&#xff1f;问题二&#xff1a;拉格朗日乘子法计算详细过程问题三&#xff1a;KKT条件求解过程问题四&#xff1a;结构风险最小化&#xff08;SRM&#xff09;的原理 在前面的讨论中…

基于 Spring Boot 博客系统开发(五)

基于 Spring Boot 博客系统开发&#xff08;五&#xff09; 本系统是简易的个人博客系统开发&#xff0c;为了更加熟练地掌握 SprIng Boot 框架及相关技术的使用。&#x1f33f;&#x1f33f;&#x1f33f; 基于 Spring Boot 博客系统开发&#xff08;四&#xff09;&#x1f…

[机器学习系列]深入解析K-Means聚类算法:理论、实践与优化

目录 一、KMeans (一)Kmeans简介 (二)Kmeans作用和优点 (三)Kmeans局限和缺点 (四)Kmeans步骤 (五)如何选取最佳的K值的三种方法 (六)手肘法和目标函数的变化两种确定K值方法的区别 (七)如何选取第一次迭代的K个类中心------KMeans方法 (八)KMeans的常用参数介绍 二、…

LeetCode 139 —— 单词拆分

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 定义 d p [ i ] dp[i] dp[i] 表示 s [ 0 , i ] s[0, i] s[0,i] 是否可以被字典中出现的单词拼接&#xff0c;那么状态转移方程为&#xff1a; d p [ i ] t r u e &#xff0c;如果存在任意 j ∈ [ 0 , i − 1…

智慧光伏电站管理系统构建与功能分析

在全球光伏产业蓬勃发展背景下&#xff0c;我国光伏制造以及光伏发电规模均位于世界首位。但是由于集中式光伏电站投资大、建设周期长、占地面积大。出于土地成本考虑&#xff0c;电站通常地处偏远地区&#xff0c;给运维管理带来了诸多不便。随着互联网、云计算、大数据、人工…

Mac环境下ollama部署和体验

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 关于ollama ollama和LLM&#xff08;大型语言模型&#xff09;的关系&#xff0c;类似于docker和镜像&#xff0c;可以在ollama服务中管理和运行各种LLM&…

【算法基础实验】图论-最小生成树Prim的延迟实现

最小生成树-Prim的延迟实现 理论基础 树的基本性质 用一条边连接树中的任意两个顶点都会产生一个新的环&#xff1b; 从树中删去一条边将会得到两棵独立的树。 切分定理的定义 定义。图的一种切分是将图的所有顶点分为两个非空且不重叠的两个集合。横切边 是一条连接两个属…

python学习笔记B-16:序列结构之字典--字典的遍历与访问

下面是字典的访问和遍历方法&#xff1a; d {10:"hello",20:"python",30:"world"} print(d[10],"--",d[20],"--",d[30]) print(d.get(10)) print("以上两种访问方式的区别是&#xff0c;d[key]若键是空值&#xff0c…

c#创建新项目

确保已安装.NET Core SDK。&#xff08;visual studio installer中可安装&#xff09; cmd中先引用到文件夹目录下。 mkdir MyConsoleApp MyConsoleApp是项目文件夹的名字。 mkdir 是一个命令行工具&#xff0c;用于在文件系统中创建新的目录&#xff08;文件夹&#xff09;…

C 语言笔记:字符串处理函数

一、获取字符串长度函数 头文件&#xff1a;#include <string.h> 函数定义&#xff1a;size_t strlen(const char *s); 函数功能&#xff1a; 测字符指针 s 指向的字符串中字符的个数&#xff0c;不包括’\0’ 返回值&#xff1a;字符串中字符个数 #include <stdio.…

DRF版本组件源码分析

DRF版本组件源码分析 在restful规范中要去&#xff0c;后端的API中需要体现版本。 3.6.1 GET参数传递版本 from rest_framework.versioning import QueryParameterVersioning单视图应用 多视图应用 # settings.pyREST_FRAMEWORK {"VERSION_PARAM": "versi…

Android(Java)项目支持Kotlin语言开发

Android&#xff08;Java&#xff09;项目通过相关Kotlin设置后&#xff0c;允许同时使用Java语言和Kotlin语言进行开发代码的。 示例环境&#xff1a; Android Studio Giraffe | 2022.3.1 Patch 3 Java 8 Kotlin 1.9.20 设置Kotlin选项&#xff1a; 第一步&#xff1a;在项…

区块链 | IPFS:Merkle DAG(进阶版)

&#x1f98a;原文&#xff1a;Merkle DAGs: Structuring Data for the Distributed Web &#x1f98a;写在前面&#xff1a;本文属于搬运博客&#xff0c;自己留存学习。 1 Merkle DAG 当我们在计算机上表示图时&#xff0c;必须通过提供节点和边的具体表示来编码我们的数据…

笔记-PPT绘图导出高清无失真图片

问题描述&#xff1a;PPT绘图已经用了高清图&#xff08;jpg、tif格式&#xff09;&#xff0c;但论文图片还是不清晰&#xff0c;打印出来还是有点糊 以下是PPT导出高清不失真图片&#xff08;emf格式&#xff09;的具体描述。 目录 一、绘图工具二、操作步骤 一、绘图工具 …

JAVA面试题---WEB部分

网络通讯 TCP与UDP TCP(Transmission Control Protocol 传输控制协议)是一种面向连接(连接导向)的、 可靠的、 基于 IP 的传输层协议。 UDP 是 User Datagram Protocol 的简称&#xff0c;中文名是用户数据报协议&#xff0c;是 OSI 参考模 型中的传输层协议&#xff0c;它是…