当前位置: 首页 > article >正文

@Autowired 和 @Resource思考(注入redisTemplate时发现一些奇怪的现象)

 1. 前置知识

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        // 配置序列化器等
        template.afterPropertiesSet();
        return template;
    }
}

Bean 的名称
名称:redisTemplate(由于没有指定bean的名称,默认使用方法名)
类型:RedisTemplate<String, Object>

@Configuration
public class RedisConfig {

    @Bean(name = "systemRedisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        // 配置序列化器等
        template.afterPropertiesSet();
        return template;
    }
}

Bean 的名称
名称:systemRedisTemplate
类型:RedisTemplate<String, Object>

@Autowired

Spring 框架提供的注解,主要用于按类型(by type)进行依赖注入。Spring 容器会根据类型查找匹配的 Bean 并进行注入。如果存在多个匹配的 Bean,Spring 会抛出 NoUniqueBeanDefinitionException 异常。(注意:他不会主动按照名称去查找,除非使用@Qualifier)

@Resource

Java EE 标准注解,主要用于按名称(by name)进行依赖注入。如果找不到名称匹配的 Bean,则按类型注入。

2. 案例分析

目前的代码

@Configuration
public class RedisConfig {

    @Bean(name = "systemRedisTemplate")
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate1(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);

        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);

        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);

        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }


    @Bean(name = "customRedisTemplate")
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate2(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);

        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);

        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);

        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }
}

@Autowired
private RedisTemplate<String ,Object> redisTemplate;

先根据类型(RedisTemplate<String ,Object>)查找bean发现找不到,然后根据名字(redisTemplate)查bean@Autowired不会自动使用名称注入,除非使用@Qualifier)报错:

NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' available: expected single matching bean but found 2: systemRedisTemplate,customRedisTemplate

解决办法

@Autowired
@Qualifier("systemRedisTemplate")  // 指定具体的 Bean
private RedisTemplate<String ,Object> redisTemplate;

或者

@Resource(name = "systemRedisTemplate")
private RedisTemplate<String ,Object> redisTemplate;

重要发现

失败:该类型的bean有两个,不会按照名称查找

@Autowired
private RedisTemplate<String ,Object > redisTemplate;

成功:@Resource 根据名称 redisTemplate 找到bean,我自己没有定义过名称为redisTemplate的bean,所以一定是SpringDataRedis自己的Bean。

@Resource
private RedisTemplate<String ,Object > redisTemplate;

失败:@Resource 根据 redisTemplate111 找不到,然后根据类型也没有找到

@Resource
private RedisTemplate<String ,Object > redisTemplate111;

成功:@Resource 根据 redisTemplate111 找不到,然后根据类型 RedisTemplate<String ,String>找到了,我没有定义过该类型的bean,所以一定是 SpringDataRedis自己的

@Resource
private RedisTemplate<String ,String> redisTemplate111;

补充:上文提到了很多SpringDataRedis自己的RedisTemplate,下面我们来看看源码

RedisAutoConfiguration 类是 Spring Boot 用于自动配置 Redis 的类


http://www.kler.cn/a/405186.html

相关文章:

  • WebApis学习笔记,第二节:高级语法
  • 贴代码框架PasteForm特性介绍之image
  • shell--第一次作业
  • ubuntu18.04 vscode c++ filesystem 使用
  • WPF窗体基本知识-笔记-命名空间
  • 用java和redis实现考试成绩排行榜
  • 商用密码产品认证名录说明
  • C++在实际项目中的应用第二节:C++与区块链
  • oracle初始化参数
  • Flutter:AnimatedBuilder自定义显示动画
  • mac-mini的时间机器,数据备份到alist 中的网盘
  • 山东春季高考-C语言-综合应用题
  • WPF里面的C1FlexGrid表格控件添加RadioButton单选
  • Hive离线数仓结构分析
  • 树莓派2装FreeBSD14.1 Raspberry Pi2 install FreeBSD14.1 00000121:error:0A000086:SSL
  • ✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
  • 深度学习中的正则化技术
  • C++中的组合模式
  • 「Mac玩转仓颉内测版23」基础篇3 - 深入理解整数类型
  • Ubuntu24.04解决向日葵安装libgconf-2-4依赖问题
  • 鸿蒙学习高效开发与测试-ArkUI 框架(2)
  • MySQL 视图使用详解
  • [C#] 关于数组的详细解释以及使用注意点
  • 【QT常用技术讲解】QSettings把中文输入到配置文件
  • Nuxt.js 应用中的 webpack:configResolved事件钩子
  • 二叉树遍历相关算法题|后序遍历非递归|下到上左到右层次遍历|先序遍历非递归(C)