redisTemplate如何注入到ValueOperations


 

今天看到Spring操作redis  是可以將redisTemplate注入到ValueOperations,避免了ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue(); 這樣來獲取ValueOperations;

@Resource(name = "redisTemplate")
private ValueOperations<String, Object> vOps;

redisTemplate並不是ValueOperations的實現類,這兩個在繼承上毫無聯系的兩個類是如何注入的呢。

后來查doGetBean()的代碼才發現有一段以前沒有詳細的去看。

        // Check if required type matches the type of the actual bean instance.
        if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
            try {
                return getTypeConverter().convertIfNecessary(bean, requiredType);
            }
            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());
            }
        }

如果你要實例化的對象和你的引用對象並不是同一種類型,也就是如redisTemplate和ValueOperations一般不是父子關系或接口實現關系,那么spring就會進行轉換。

用什么轉換呢?Spring的editor。

String editorName = targetType.getName() + "Editor";
        try {
            Class<?> editorClass = cl.loadClass(editorName);
            if (!PropertyEditor.class.isAssignableFrom(editorClass)) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Editor class [" + editorName +
                            "] does not implement [java.beans.PropertyEditor] interface");
                }
                unknownEditorTypes.add(targetType);
                return null;
            }
            return (PropertyEditor) instantiateClass(editorClass);
        }

spring會去加載 ValueOperations+Editor,即ValueOperationsEditor的類。且此類必須要實現PropertyEditor接口。

而我們在ValueOperations的包目錄下確實會找到ValueOperationsEditor。

class ValueOperationsEditor extends PropertyEditorSupport {

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

這個類非常簡單,它重寫了setValue方法,將redisTemplate中的opsForValue()返回值set進去,而opsForValue()返回值就是繼承了ValueOperations的DefaultValueOperations。

這樣我們用editor get value的時候就能獲取到DefaultValueOperations了。就可以將DefaultValueOperations注入到ValueOperations中去了。

 

做個實驗,寫兩個類

 

public class ClassA {
    private String msg;
    public ClassA(String msg){
        this.msg=msg;
    }
    public void hi(){
        System.out.println(msg);
    }
}

 

@Component
public class ClassB {
    public ClassA getA(){
        return new ClassA("this is A from B");
    }
}

類B有個方法可以獲取A類實例,我們將此注入到A對象中。

public class EditorTest extends BaseJunitTest{
    
    @Resource(name="classB")
    private ClassA a; 
    
    @Test   
    public void test(){
        a.hi();
    }
}
BaseJunitTest配置了一些spring的XML配置文件 不需要管它。
此時我們還需要寫一個ClassAEditor類。如果沒有editor類的話當然會注入不了 並拋出一個異常
Bean named 'classB' is expected to be of type 'xxx.test.ClassA' but was actually of type 'xxx.test.ClassB'
我們完成ClassAEditor
public class ClassAEditor extends PropertyEditorSupport{
      public void setValue(Object value) {
          super.setValue(((ClassB)value).getA());
      }
}
 
        

判斷略去不寫。

運行程序,得到正確結果

 

非常有意思的一個細節,工廠模式的一種體現。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM