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);
 
	@Resource
	private 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.mfbz.cn/a/588742.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【linux学习指南】linux指令与实践文件编写

文章目录 &#x1f4dd;前言&#x1f320; linux目录结构&#x1f309;linux命令介绍 &#x1f320;pwd命令&#x1f309;mkdir指令&#xff08;重要&#xff09; &#x1f320;cd 指令&#x1f309;touch指令 &#x1f320;rmdir指令 && rm 指令&#xff08;重要&…

串的介绍与类型定义

串的定义 相关术语 应用 串类型定义 顺序存储实现 为了方便操作&#xff0c;数组下标从1开始存储 链式存储实现

【Leetcode】二叉树基础题思路

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;Leetcode刷题 目录 1.单值二叉树2.相同的树3.对称二叉树4.另一棵树的子树 1.单值二叉树 题目链接&#xff1a;965.单值二叉树 题目描述&#xff1a; 单值二叉树是所有节点的值都相同的二叉树。实现…

MySQL LIKE通配符(%,_)及escape实例讲解

LIKE操作符常用于模式匹配查询数据。以正确的方式使用LIKE运算符对于提高查询性能至关重要。 LIKE操作符允许您从基于指定的模式选择表中的数据。因此&#xff0c;LIKE操作符经常用于SELECT语句的WHERE子句中。 MySQL提供了两个通配符与LIKE操作符一起使用&#xff1a;百分比…

LeetCode 98.验证二叉搜索树

题目描述 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左 子树 只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例 1&#xff…

移植 SquareLine 导出的 UI 源码到 HMI-Board

目录 准备工具创建 HMI 工程设计 UIUI 移植板级验证更多内容 HMI-Board 为 RT-Thread 联合瑞萨推出的高性价比图形评估套件&#xff0c;取代传统的 HMI 主控板 硬件&#xff0c;一套硬件即可实现 HMI IoT 控制 的全套能力。依托于瑞萨高性能芯片 RA6M3 及 RT-Thread 软件生态…

leetcode870.优势洗牌

题目描述&#xff1a; 给定两个长度相等的数组 nums1 和 nums2&#xff0c;nums1 相对于 nums2 的优势可以用满足 nums1[i] > nums2[i] 的索引 i 的数目来描述。 返回 nums1 的任意排列&#xff0c;使其相对于 nums2 的优势最大化。 示例一&#xff1a; 输入&#xff…

nginx--平滑升级

失败了&#xff0c;等我拍好错继续更新 命令 选项说明 帮助: -? -h 使用指定的配置文件: -c 指定配置指令:-g 指定运行目录:-p 测试配置文件是否有语法错误:-t -T 打印nginx的版本信息、编译信息等:-v -V 发送信号: -s 示例: nginx -s reload 信号说明 立刻停止服务:stop,相…

笔记:编写程序,绘制一个展示支付宝月账单报告的饼图,

文章目录 前言一、饼图是什么&#xff1f;二、分析题目三、编写代码总结 前言 编写程序&#xff0c;绘制一个展示支付宝月账单报告的饼图&#xff0c;实现过程如下&#xff1a; &#xff08;1&#xff09; 导入 matplotlib.pyplot 模块&#xff1b; &#xff08;2&#xff09;…

主成分分析在R语言中的简单应用:使用mvstats包

在数据科学领域&#xff0c;主成分分析&#xff08;PCA&#xff09;是一种广泛使用的技术&#xff0c;主要用于数据降维和探索性数据分析。PCA可以帮助我们发现数据中的模式&#xff0c;减少数据集的复杂性&#xff0c;同时保持数据中最重要的特征。本文将介绍如何在R语言中使用…

【经典算法】LeetCode112. 路径总和(Java/C/Python3/Go实现含注释说明,Easy)

作者主页&#xff1a; &#x1f517;进朱者赤的博客 精选专栏&#xff1a;&#x1f517;经典算法 作者简介&#xff1a;阿里非典型程序员一枚 &#xff0c;记录在大厂的打怪升级之路。 一起学习Java、大数据、数据结构算法&#xff08;公众号同名&#xff09; ❤️觉得文章还…

实时监控RTSP视频流并通过YOLOv5-seg进行智能分析处理

在完成RTSP推流之后&#xff0c;尝试通过开发板接收的视频流数据进行目标检测&#xff0c;编写了一个shell脚本实现该功能&#xff0c;关于视频推流和rknn模型的部署请看之前的内容或者参考官方的文档。 #!/bin/bash # 设置脚本使用的shell解释器为bashSEGMENT_DIR"./seg…

OceanBase开发者大会实录-陈文光:AI时代需要怎样的数据处理技术?

本文来自2024 OceanBase开发者大会&#xff0c;清华大学教授、蚂蚁技术研究院院长陈文光的演讲实录—《AI 时代的数据处理技术》。完整视频回看&#xff0c;请点击这里&#xff1e;> 大家好&#xff0c;我是清华大学、蚂蚁技术研究院陈文光&#xff0c;今天为大家带来《AI 时…

JUC线程

进程和线程&#xff1a; 进程&#xff08;Process&#xff09;是计算机中的程序关于某数据集合上的一次运行活动&#xff0c;是系统进行资源分配的基本单位&#xff0c;是操作系统结构的基础。 线程&#xff08;英语&#xff1a;thread&#xff09;是操作系统能够进行运算调度…

python基础语法--函数

一、函数概述 函数就是执行特定任务完成特定功能的一段代码。可以在程序中将某一段代码定义成函数&#xff0c;并指定一个函数名和接收的输入&#xff08;参数&#xff09;&#xff0c;这样就可以在程序的其他地方通过函数名多次调用并执行该段代码了。 每次调用执行后&#…

Ubuntu如何安装Calicoctl

在 Ubuntu 上安装 Calico 通常涉及几个步骤。以下是一般的安装过程&#xff1a; 安装 etcd 或使用 Kubernetes 集群的现有 etcd&#xff1a; 如果你使用的是独立的 etcd&#xff0c;请确保 etcd 在可访问的地方运行。如果你使用的是 Kubernetes 集群&#xff0c;通常会有一个 e…

用户中心(终)

文章目录 Ant Design Pro&#xff08;Umi 框架&#xff09;ProComponents 高级表单待优化点 todo注册逻辑增加注册页面页面重定向问题注册页面 **获取用户的登录态****前端用户管理功能** Ant Design Pro&#xff08;Umi 框架&#xff09; app.tsx 项目全局入口文件&#xff0c…

【车载开发系列】MCAL基本概念

【车载开发系列】MCAL基本概念 【车载开发系列】MCAL基本概念 【车载开发系列】MCAL基本概念一. BSW与MCAL1&#xff09;BSW-服务层2&#xff09;BSW-ECU抽象层3&#xff09;MCAL驱动层 二. MCAL基本概念三. MCAL组成1&#xff09;PORT2&#xff09;DIO3&#xff09;ADC4&#…

排序算法——直接插入排序

直接插入排序与希尔排序是插入排序的两个分支&#xff0c;直接插入排序是较为简单的一种排序算法&#xff0c;同时也是众多算法实现或优化的基石。 前提&#xff1a; 插入排序&#xff1a;有一个已经有序的数据序列&#xff0c;要求在这个已经排好的数据序列中插入一个数&…

BigKey的危害

1.2.1、BigKey的危害 网络阻塞 对BigKey执行读请求时&#xff0c;少量的QPS就可能导致带宽使用率被占满&#xff0c;导致Redis实例&#xff0c;乃至所在物理机变慢 数据倾斜 BigKey所在的Redis实例内存使用率远超其他实例&#xff0c;无法使数据分片的内存资源达到均衡 Redis阻…
最新文章