Spring 奇特的类型转化

今天有个比较好玩的问题记录下 。 首先说下问题:
在 Spring Data Redis 官方文档中 , 可以看到这样一个常规用法 。
这里注入 XxxOps , 为什么指定的都是 redisTemplate , 原因是?
首先第一想法肯定是redistemplate 是子类实现 , xxoperations是父类 。 那么真的是这样吗?
那么先从继承关系看 。
RedisTemplate继承关系是
Spring 奇特的类型转化文章插图
ListOperations继承关系
Spring 奇特的类型转化文章插图
可以看到RedisTemplate 和 ListOperations 并没有继承关系 , 这里是怎么把 RedisTemplate 注入到 ListOperations 类型上去的呢?而且不但可以将 RedisTemplate 注入到 ListOperations, 也可以注入到 ValueOperations、SetOperations、ZSetOperations、HashOperations 等类型上 。
这时候就看看源码吧 。
所有Ops的类都继承了AbstractOperations这个类 。 这个类的构造方法是
final RedisTemplate template; AbstractOperations(RedisTemplate template) {this.template = template; }然后所有的Ops的构造方法是 , 例如ListOperations的
DefaultValueOperations(RedisTemplate template) {super(template); }然后RedisTemplate的实现是
public class RedisTemplate extends RedisAccessor implements RedisOperations, BeanClassLoaderAware { private final ValueOperations valueOps = new DefaultValueOperations<>(this); private final ListOperations listOps = new DefaultListOperations<>(this); private final SetOperations setOps = new DefaultSetOperations<>(this); private final StreamOperations streamOps = new DefaultStreamOperations<>(this, new ObjectHashMapper()); private final ZSetOperations zSetOps = new DefaultZSetOperations<>(this); private final GeoOperations geoOps = new DefaultGeoOperations<>(this); private final HyperLogLogOperations hllOps = new DefaultHyperLogLogOperations<>(this); private final ClusterOperations clusterOps = new DefaultClusterOperations<>(this);这时是不是就有个想法是 , 通过构造方法注入的形式实现的呢?
于是我模拟写了个Test Demo
public class Test1 {final Test test;public Test1(Test test) {this.test = test;}public void a(){System.out.println(11);test.bb();}public void bb(){System.out.println(test.test1());}}@Component("test")public class Test{private Test1 test1 = new Test1(this);public Test1 test1(){return test1;}public void bb(){System.out.println(22);}}@RestControllerpublic class TestController{@Resource(name="test")private Test1 test1;@RequestMapping("/test")public String test(){test1.a();test1.bb();return "json";}}可以看下运行结果
Spring 奇特的类型转化文章插图
这时候就认为确实是通过构造方法注入的形式实现 。 但是这时候有人说不是 , 它是通过PropertyEditor实现的 。 那么PropertyEditor是怎么做的呢?
Spring 框架可以通过 java.beans.PropertyEditor 接口的实现类来实现类型转换 。 Spring Data Redis 提供了 ListOperationsEditor 可以将 RedisTemplate 转为 ListOperations 。 具体如下:


推荐阅读