依赖dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- 以上为springboot启动器,springData启动器(Redistemplate) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 测试类启动器 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- 方便为RedisTemplate的key-value做序列化操作 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 数据库连接 -->
解决
1.关于 @Resource(name = “redisTemplate”) 为何可以为 ValueOperations 类型注入实体
@Autowired
private RedisTemplate redisTemplate;
@Resource(name = "redisTemplate")
private ValueOperations<String, String> strOperation;
可以延伸为实例化的对象和你的引用对象并不是同一种类型的问题。也就是如redisTemplate和ValueOperations一般不是父子关系或接口实现关系,那么spring就会进行转换。转换的方式就是通过Spring的Editor做的。
在项目启动过程中,spring会进行实例化和注入操作
在org.springframework.beans.factory.support.AbstractBeanFactory 类中的 doGetBean 方法中,实际上是调用了 org.springframework.beans.TypeConverterDelegate 类中convertIfNecessary方法,待进入以下步骤来处理实例化类型与引用类型不同的问题
// Value not of required type?
if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) &&
convertedValue instanceof String) {
TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor();
if (elementTypeDesc != null) {
Class<?> elementType = elementTypeDesc.getType();
if (Class.class == elementType || Enum.class.isAssignableFrom(elementType)) {
convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
}
}
}
if (editor == null) {
//此处去获取相关Editor,在该问题中为ValueOperationsEditor类
editor = findDefaultEditor(requiredType);
}
convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
}
findDefaultEditor方法是获取相关Editor,在该问题中为ValueOperationsEditor的类。且此类必须要实现PropertyEditor接口。
doConvertValue的作用
Object convertedValue = newValue;
if (editor != null && !(convertedValue instanceof String)) {
try {
editor.setValue(convertedValue);
Object newConvertedValue = editor.getValue();
if (newConvertedValue != convertedValue) {
convertedValue = newConvertedValue;
// Reset PropertyEditor: It already did a proper conversion.
// Don't use it again for a setAsText call.
editor = null;
}
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("PropertyEditor [" + editor.getClass().getName() + "] does not support setValue call", ex);
}
// Swallow and proceed.
}
}
1).先通过editor.setValue将实例化对象通过ValueOperationsEditor的setValue方法保存替换掉。ValueOperationsEditor类中的setValue方法已被重写,实例化对象通过符合条件的RedisOperations实例的opsForValue方法保存为ValueOperations类型了。而实现了RedisOperations接口的opsForValue方法只有RedisTemplate类。
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);
}
}
2).通过editor.getValue()再获取该值。则可以注入。