搞不懂,为啥redis操作对象的注入方式跟平常的不一样?

Redis的基本操作 SETEX key seconds value设置指定key的值,并将key的过期时间设为seconds 秒 setex name 30 tom。有序集合(sorted set/zset):集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素。HSET key field value 将哈希表key中的字段field的值设为value。Redis存储的是key-value结构的数据,其中key是字符串类型,集合(set):无序集合,没有重复元素,类似于Java中的HashSet。 阅读详情

不知道大家平时有没有见过或者写过这样的代码。

这样写是错误的吧,idea编译器都识别报错了呀?

明明两个不同类型的类,也能通过spring注入?

为啥这些redis的操作类都通过redisTemplate注入?

既然我这样写了,自然是没有问题的。

要不,带着这些问题跟我继续往下看?

提出猜想

我们都知道ValueOperations操作对象都是能够直接通过RedisTemplate直接获得:

ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();

那么我们是不是可以有以下猜想(以注入ValueOperations为例)。

  • @Resource(name = "redisTemplate")

    • ①首先从spring容器中获取到已经初始化好的RedisTemplate对象。

    • ②再通过redisTemplate.opsForValue()获取到ValueOperations对象。

  • private ValueOperations<String, String> stringValueOperations;

    • ③最后获取的ValueOperations对象赋值给stringValueOperations变量。

验证猜想

获取bean:doGetBean

既然是spring的注入问题,我们就需要翻开获取spring bean逻辑的代码doGetBean。

protected <T> T doGetBean(
      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException

说明一下参数的含义

  • name: 需要注入的对象名
  • requiredType: 期望返回对象的class
  • args: 显式参数创建bean实例时要使用的参数
  • typeCheckOnly: 是否为类型检查获取实例

而我们需要重点关注的就两个参数:name和requiredType。

根据我们的业务场景,大概来理解下这两个参数

name是不是就等于"redisTemplate"

而requiredType是不是就是ValueOperations.class

这时,你有没有恍然大悟的感觉,原来spring本来就是支持注入的bean类型和返回的类型不一样的啊。

那spring是怎么实现的呢,我们接着往下看(只截取关键代码)

// 如果从spring容器获取的对象和期望返回的对象类型不一样,执行此逻辑
if (requiredType != null && !requiredType.isInstance(bean)) {
   try {
      T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
      if (convertedBean == null) {
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
      return convertedBean;
   }
   catch (TypeMismatchException ex) {
      if (logger.isDebugEnabled()) {
         logger.debug("Failed to convert bean '" + name + "' to required type '" +
               ClassUtils.getQualifiedName(requiredType) + "'", ex);
      }
      throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
   }
}

重点就是T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType) 这行代码了。 他实现了bean的转换逻辑

转换bean:doConvertValue

深入这行代码,就能找到真正执行转换逻辑的代码(TypeConverterDelegate.class)。篇幅有限,只截取关键代码。

@Nullable
private Object doConvertValue(@Nullable Object oldValue, @Nullable Object newValue,
      @Nullable Class<?> requiredType, @Nullable PropertyEditor editor) {

   Object convertedValue = newValue;

   if (editor != null && !(convertedValue instanceof String)) {
      try {
         editor.setValue(convertedValue);
         Object newConvertedValue = editor.getValue();
         if (newConvertedValue != convertedValue) {
            convertedValue = newConvertedValue;
            editor = null;
         }
      }
      catch (Exception ex) {
         if (logger.isDebugEnabled()) {
            logger.debug("PropertyEditor [" + editor.getClass().getName() + "] does not support setValue call", ex);
         }
      }
   }

   Object returnValue = convertedValue;

   return returnValue;
}

重点需要关注两行代码

editor.setValue(convertedValue);

Object newConvertedValue = editor.getValue();

可以看到spring将两个对象的转换交给了从spring容器获取的bean和PropertyEditor对象去处理:

  • spring先是给PropertyEditor对象设置了从spring容器中获取到的对象

  • 然后直接从PropertyEditor对象获取对象

  • 最后就返回了这个对象

那么PropertyEditor这个对象是啥,他又是怎么组合从spring容器获取的bean从而获取到想要的对象的呢?

PropertyEditor

简介

官方注释对PropertyEditor进行了说明

PropertyEditor类为希望允许用户编辑给定类型的属性值的GUI提供支持。

PropertyEditor支持显示和更新属性值的各种不同方式。大多数PropertyEditors只需要支
持此API中可用的不同选项的子集。

Simple PropertyEditors可能只支持getAsText和setAsText方法,不需要支持
paintValue或getCustomEditor。更复杂的类型可能无法支持getAsText和setAsText,
但将支持paintValue和getCustomEditor。

每个propertyEditor都必须支持三种简单显示样式中的一种或多种。
因此,它可以(1)支持isPaintable,或者(2)从getTags()返回一个非null String[],
并从getAsText()中返回非null值,或者(3)只从getAs文本()返回非null String。

当参数对象的类型为propertyEditor时,每个属性编辑器都必须支持对setValue的调用。
此外,每个属性编辑器必须支持自定义编辑器或支持setAsText。

每个PropertyEditor都应该有一个空构造函数。

说白了,JDK提供了这个接口,就是为了将外部设置的值(RedisTemplate)转换为内部的属性值(value = ValueOperations)。

跟ValueOperations的关系

先抛开PropertyEditor这个对象,回到我们要转换的类型ValueOperations上,打开ValueOperations类所在的位置。

有没有发现所在目录下,每一种Operations都有对应的Editor,我们选择ValueOperationsEditor看看他的UML类图

果然,就是我们要找的PropertyEditor!

ValueOperationsEditor源码

接着我们来看下ValueOperationsEditor的源码,看他都做了些啥。

class ValueOperationsEditor extends PropertyEditorSupport {
    ValueOperationsEditor() {
    }

    public void setValue(Object value) {
        if (value instanceof RedisOperations) {
            super.setValue(((RedisOperations)value).opsForValue());
        } else {
            throw new IllegalArgumentException("Editor supports only conversion of type " + RedisOperations.class);
        }
    }
}

果然,跟我们的猜想一样,最终就是通过opsForValue()方法从RedisTemplate获取到真正的操作对象,并设置到Editor对象的value属性中,然后调用getValue返回我们期望获取的对象ValueOperations。

总结

事实证明了我们的猜想大致的思路是没问题的,但是需要补充点细节。

那最后,我们就将之前的猜想补充成最终的结论吧。

  • 首先获取到spring容器中的RedisTemplate对象
  • 然后获取到ValueOperations对应的编辑类ValueOperationsEditor
  • 将RedisTemplate对象通过set方法给ValueOperationsEditor的属性值value赋值
  • 最后通过get方法得到属性值,即ValueOperations对象
Redis以及SpringDataRedis的操作 Redis是一个基于内存的 key-value 结构数据库基于内存存储,读写性能高适合存储热点数据(热点商品、资讯、新闻)企业应用广泛Redis与MySql的区别:redis将数据存入内存,读写性能高,mysql存在了磁盘上,存储介质不同,redis通过key-value键值对存储,mysql通过二维表存储。 阅读详情

相关推荐

【SpringBoot】34、SpringBoot整合Redis实现序列化存储Java对象

前面我们已经介绍过【SpringBoot】十七、SpringBoot 中整合 Redis,我们可以看出,在 SpringBoot 对 Redis 做了一系列的自动装配,使用还是非常方便的 一、背景 1、思考‘ 通过我们前面的学习,我们已经可以往 Redis 中存入字符串,那么我们要往 Redis 中存入 Java 对象该怎么办呢? 2、方案 我们可以将 Java 对象转化为 JSON 对象,然后转为 JSON 字符串,存入 Redis,那么我们从 Redis 中取出该数据的时候,我们也只能取出字符串,并转

JACKAL 22万+

Redis基础 与 ValueOperations操作Redis

Redis基础 与 ValueOperations操作Redis Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库

z.x.k 的博客 4461

【Windows】 解决联想为主的所有自带摄像头(integrate camera)打不开的毛病(特别点名小新、thinkbook、thinkpad、y7000...)

解决联想系列电脑打不开自带摄像头的问题

Iamruzi的csdn博客 3万+

Redis数据类型&RedisTemplate用法详解

目录 Redis 数据类型 一、Redis 字符串(String) -- ValueOperations 二、Redis 哈希(Hash) --HashOperations 三、Redis 列表(List) --ListOperations 四、Redis 集合(Set) -- SetOperations 五、Redis 有序集合(sorted set) -- ZSetOperations Redis 数据类型 Redis支持五种数据类型:string(字符串),hash...

weixin_44253327的博客 1703

kubedns-coredns部署pod出现not ready问题

文章目录遇到的问题1、发现问题2、排查问题3、解决方法 coredns的实例health_check不通过的问题,排查和解决方法 遇到的问题 1、发现问题 pod启动但是未ready 查看是readiness失败 使用对应的URL进行curl,发现真的返回503 2、排查问题 查看错误日志,发现一堆这个错误"waiting on : kubernetes" 网上相关的问题解答 这个跟测试场景不一样,这个案例是开了防火墙,可以确认我这个案例的机器没有开防火墙,但它提醒了一点,coredns是需要访问ap

u012533481的博客 2844

三相Vienna整流器过零点电流畸变?试试这个SVPWM调制波补偿技巧

本文针对三相Vienna整流器在电流过零点附近出现的电流畸变问题,提出了一种基于SVPWM调制波补偿的有效解决方案。该方法通过注入零序分量重构占空比,巧妙解决因拓扑约束导致的调制矛盾,在基本不增加计算复杂度的前提下,显著平滑电流波形,降低THD。

weixin_29212867的博客 115

ValueOperations<String, Object> ValueOperations = redisTemplate.opsForValue();中ValueOperations的所有方法详

ValueOperations ValueOperations = redisTemplate.opsForValue();中ValueOperations的所有方法详细

不太聪明qtfj的博客 1881

Electron多窗口开发避坑指南:Pinia状态同步的3种解决方案对比

本文深入探讨了在Electron多窗口应用中实现Pinia状态同步的三种核心方案。针对Electron多窗口架构下状态隔离的挑战,文章对比了基础事件通信、共享存储以及智能Pinia插件等方案的优劣与适用场景,并提供了生产级的实现指南与选型建议,帮助开发者构建健壮高效的桌面应用。

spice的博客 479

sprintboot 集成redis操作时 redisTemplate注入为空

问题描述 springboot2.*集成redis时,redis工具类中的redisTemplate注入后总是为空。 问题代码还原: 1、工具类定义成静态工具类,@Resource注入redisTemplate /** * Redis工具类 */ public final class RedisUtil { @Resource private RedisT...

胡杰的专栏 7767

运维与软件实施课表

运维与软件实施课表 课程 章节编号 章节 课程地址 软件及操作系统基础 ch01 软件及操作系统基础01 实施、运维工程师基本技能:https://blog.youkuaiyun.com/qq_28189423/article/details/82700539 老毛桃制作winPE镜像:https://blog.youkuaiyun.com/qq_2818942...

Mr.O~的博客 1万+

Zynq UltraScale+ MPSoC-dp14 standalone

EDID HDCP AR# 64652 How to port the DisplayPort 1.4 TX subsystem example to a custom board dp v2.1 example design color format change DisplayPort-DP接口知识

zhuxl24的博客 2671

redis对象的存取操作

redis存入对象和将对象取出来 在使用redis时,可以将字符串、列表、集合、可排序集合、哈希等数据结构写入,但是写入对象是比较麻烦。 这里提供一个将对象转为byet数组存储到redis中,然后需要的时候也可以将以byte数组形式写入redis的对象转换为对象提取出来的工具类: package cn.xdl.ydma.entity; import java.io.ByteArrayInputS...

weixin_45389262的博客 1418

Matlab+Matpower实战:手把手教你生成IEEE14节点FDIA攻击数据集(附完整代码)

本文提供了一份基于Matlab与Matpower工具构建IEEE14节点FDIA攻击数据集的完整实战指南。通过动态负荷数据模拟、潮流计算、状态估计及隐蔽攻击向量注入,手把手教你生成可用于电力系统网络安全研究的仿真数据集,并附有核心代码与调试技巧。

bean的博客 399

Spring+Mybatis+redis整合(用依赖注入的方式手动修改缓存)

现在开始Spring+mybatis+redis的整合,一开始我想的是Spring+SpringMVC+Mybatis+redis进行整合,但是慢慢整合着就就感觉前面的会了,后面的肯定也就会了,也就不整合后面的了,如果感觉还是很模糊的话,你可以根据下面的慢慢的来整合你肯定会这么觉的 先看看我的目录结构 首先spring-server.xml <?xml version="1.0" en...

胖墩的IT博客 2478

uniapp APP端:蓝牙报错writeBLECharacteristicValue:fail property not support(uni.writeBLECharacteristicVal)

uni-app 蓝牙fail property not support、发现不了服务特征值的问题、突然发现微信蓝牙小秘密,使用uni-app编译成安卓APP后报错writeBLECharacteristicValue:fail property not support,发现不了服务特征值,uniApp APP调用蓝牙API发送指令过快导致,uniapp 蓝牙 writeBLECharacteristicValue property_not_support iOS Android BLE GATT 特征值写入

✅ 精选推荐文章 2944

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

关于Redis序列化反序列化不一致问题引起对Spring自动注入方式的思考

因此IOC中会存在一个StringRedisTemplate<String, String> 的bean,还记得我们前面说过@Autowired注解是通过byType方式装配,StringRedisTemplate<String, String> 是RedisTemplate<String, String>子类,因此符合byType规则,因此返回的是spring提供的StringRedisTemplate。项目中推荐使用构造参数方式注入,但是为了方便开发人员更倾向使用@Autowired注解实现自动注入。

I_am_a_losser的博客 273

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

spring boot下使用RedisTemplate操作redis存取对象

在spring boot环境下有个StringRedisTemplate对象,默认已经为我们配置好了,只需要自动注入过来就能用,但是使用它只能在Redis中存放字符串。具体操作如下: @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @...

混合动力火锅的博客 4万+

springboot集成redis,并提供redis操作工具类

1、首先贴上配置信息(本人使用的是springboot2.0以上版本): spring: datasource: url: jdbc:mysql://127.0.0.1:3306/pcms?useUnicode=true&charaterEncoding=utf-8&allowMultiQueries=true&serverTimezone=GMT ...

li_jiazhi的博客 817

Java使用redis:将数据插入redis缓存的方式

背景:当redis里面需要存储 “key-字符串,value-对象” 时,是不能直接存对象,而是需要将序列化后或转换为JSON后的对象存进redis。redis没有实现内部序列化对象的功能,所以需要自己提前序列化对象及转换为Json对象。序列化介绍:序列化的方法有很多,比如java原生序列化(需要实现Serializable接口)、json序列化、protobuff序列化。protobuff序列化...

HeJD的博客 8万+

SQL 注入与 Redis 缓存问题总结

攻击者把恶意字符串作为输入,拼接进 SQL 语句中。数据库按“正常 SQL”执行这些内容,造成绕过登录、泄露数据、删表等后果。用户输入直接参与字符串拼接构造 SQL。遇到这种拼接,就说明写法有问题。新代码统一用预处理语句,旧代码至少先做转义。不要拼接 SQL,用预处理语句,旧代码至少先做转义。热点 key 过期瞬间被打爆,用互斥锁或逻辑过期 + 异步刷新。一堆 key 同时过期或 Redis 整体挂掉,用随机过期时间、多级缓存、预热、降级限流。

2504_93605592的博客 1614

为什么可以自动注入RedisTemplate对象

什么是RedisTemplate? 答:是Spring Data Redis中提供的一个高度封装的类,针对redis客户端中大量的api进行了归类封装,讲同一类型操作封装为operation接口。 问题环境: 在JAVA中,当我们创建了个SpringBoot项目时,我们想要使用RedisTemplate,但是我们没有并没有在项目中定义RedisTemplate,但还是可以使用@Autowired自动注入其对象。 但是可以实现自动注入: 原因: 在我们查看该项目jar包管理目录中找到spr

m0_64436238的博客 2152

spring集成redis,序列化对象,以及websocket依赖注入

最近业务在使用websocket开发一个聊天系统,打算使用redis存储聊天记录。       首先导入spring集成redis的包spring-data-redis-1.6.2.RELEASE.jar, redis java驱动包jedis-2.9.0.jar        spring配置文件 <beans xmlns="http://www.springframework.org/

timeless的博客 1950

redis在控制类中注入失败

Redis 在控制类中注入失败的解决方案 在使用 Redis 的过程中,很多开发者可能会遇到在控制类中注入 Redis 客户端失败的情况。本文将为您详细介绍这一过程,并提供解决方案。我们将分步骤解读整个流程,并在每一步中给出示例代码和详细注释。 整体流程 以下是将 Redis 注入到控制类中的基本步骤: 步骤 描述 ...

weixin_35796523的博客 180

Spring选择哪种注入方式

即使是面试跳槽,那也是一个学习的过程。只有全面的复习,才能让我们更好的充实自己,武装自己,为自己的面试之路不再坎坷!今天就给大家分享一个Github上全面的Java面试题大全,就是这份面试大全助我拿下大厂Offer,月薪提至30K!我也是第一时间分享出来给大家,希望可以帮助大家都能去往自己心仪的大厂!为金三银四做准备!

keyoukewude的博客 939
上一篇: JAVA面试基础题目,不紧跟时代的面试题看它有什么意义?
下一篇: Project Reactor源码阅读-flatMap
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值