1. 前置知识
@Configuration
public class RedisConfig {@Beanpublic 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序列化方式采用jacksontemplate.setValueSerializer(jackson2JsonRedisSerializer);// hash的value序列化方式采用jacksontemplate.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序列化方式采用jacksontemplate.setValueSerializer(jackson2JsonRedisSerializer);// hash的value序列化方式采用jacksontemplate.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 的类