StringRedisTemplate注入问题

1
`Bean named 'redisTemplate' is expected to be of type 'org.springframework.data.redis.core.StringRedisTemplate' but was actually of type 'org.springframework.data.redis.core.RedisTemplate'`

翻译:Spring框架期望一个名为 ‘redisTemplate’ 的bean 应该是类型为 ‘org.springframework.data.redis.core.StringRedisTemplate’,但实际上它是类型为 ‘org.springframework.data.redis.core.RedisTemplate’。

解决方式

方案一:改变注入方式

@Resource改为@Autowired

方案二:改命名

redisTemplate/template改为stringRedisTemplate

深入探究

两种注解区别

来源不同
  • @Autowired 是Spring提供的注解,它可以用来自动装配Spring容器中的bean,通常通过类型匹配来注入依赖。
  • @Autowired跟Spring框架强耦合了, 如果换成其他框架,@Autowired就没作用了。
  • @Resource 是Java EE 提供的注解,它也可以用来注入依赖,但更加通用,不仅可以注入Spring容器中的bean,还可以注入其他Java EE容器中的资源,通常通过名称匹配来注入依赖。
  • @Resource是JSR-250提供的,它是Java标准,绝大部分框架都支持。
内部参数定义不同
@Resource注解源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public @interface Resource {
// bean的名称
String name() default "";
// 指定JNDI名称,查找资源。指定了lookup,则忽略name属性
String lookup() default "";
// 指定要注入的bean或者资源的类型。默认为 Object.class
Class<?> type() default Object.class;
// 资源的认证类型,默认为CONTAINER,表示容器认证;另外还有 APPLICATION,表示应用程序认证
AuthenticationType authenticationType() default Resource.AuthenticationType.CONTAINER;
// 资源是否共享,默认为 true
boolean shareable() default true;
// 指定JNDI名称,查找EJB组件,指定了mappedName,则忽略name属性
String mappedName() default "";
// 描述信息,用于文档说明
String description() default "";

public static enum AuthenticationType {
CONTAINER,
APPLICATION;

private AuthenticationType() {
}
}
}
@Autowired注解源码
1
2
3
4
public @interface Autowired {
// 是否开启自动注入,不开启自动装配,可设为false。
boolean required() default true;
}

required():指示被注解的依赖是否是必需的。默认值为 true,表示依赖是必需的,如果找不到匹配的bean,则会抛出异常。如果将其设置为 false,则表示依赖是可选的,如果找不到匹配的bean,Spring容器将不会抛出异常,而是将该属性设置为 null

例如,如果 @Autowired(required = false),并且找不到匹配的bean,则不会抛出异常,而是将依赖设置为 null

注解应用范围不同

@Autowired能够用在构造方法、成员变量、方法参数以及注解上

1
2
3
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented

@Resource能用在类、成员变量和方法参数上

1
2
3
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Resources.class)
装配方式不同

@Autowired默认按type自动装配,而@Resource默认按name自动装配。当然,@Resource注解可以自定义选择,如果指定了name,则根据name自动装配,如果指定了type,则用type自动装配。

装配顺序不同

@Autowired 装配顺序
@Autowired默认先与byType进行匹配,如果发现找到多个Bean,则又按照byName方式进行匹配,如果还有多个Bean,则报出异常。装配顺序如下图所示。
图片一

@Resource 装配顺序
1)如果同时指定name和type,则从Spring上下文中找到与它们唯一匹配的Bean进行装配,如果找不到则抛出异常,具体流程如下图所示。
图片二

2)如果指定name,则从上下文中查找与名称(ID)匹配的Bean进行装配,如果找不到则抛出异常,具体流程如下图所示。
图片三

3)如果指定type,则从上下文中找到与类型匹配的唯一Bean进行装配,如果找不到或者找到多个就会抛出异常,具体流程如下图所示。
图片四

4)如果既没有指定name,也没有指定type,则自动按byName方式进行装配。如果没有匹配成功,则仍按照type进行匹配,具体流程如下图所示。
图片雾