• 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());
          }
    }
    
    

    判断略去不写。

    运行程序,得到正确结果

    非常有意思的一个细节,工厂模式的一种体现。

     
  • 相关阅读:
    错排问题
    用GDAL/OGR去读shapefile
    聊聊MyBatis缓存机制
    一份平民化的应用性能优化检查列表(完整篇)--转
    微服务实战(七):从单体式架构迁移到微服务架构
    微服务实战(六):选择微服务部署策略
    微服务实战(五):微服务的事件驱动数据管理
    微服务实战(四):服务发现的可行方案以及实践案例
    微服务实战(三):深入微服务架构的进程间通信
    微服务实战(一):微服务架构的优势与不足
  • 原文地址:https://www.cnblogs.com/tangyuanyuan/p/8067923.html
Copyright © 2020-2023  润新知