Spring注入的类型和成员变量类型不同的原理?

发布于 2022-09-03 19:42:09 字数 746 浏览 9 评论 0

在看Spring Data Redis,看到RedisTemplate可以注入到ListOperations,请问这两种不同的类型是如何实现注入的?

public class Example {

    // inject the template as ListOperations
    // can also inject as Value, Set, ZSet, and HashOperations
    @Resource(name="redisTemplate")
    private ListOperations<String, String> listOps;

    public void addLink(String userId, URL url) {
        ...
    }
}
<bean id="redisTemplate" 
    class="org.springframework.data.redis.core.RedisTemplate" 
    p:connection-factory-ref="jedisConnFactory"/>

以上RedisTemplate和ListOperations是两个不同类型,为什么可以注入成功?

文档:http://projects.spring.io/spr...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梅倚清风 2022-09-10 19:42:09

转自:https://xxgblog.com/2020/03/1...

问题

在 Spring Data Redis 官方文档中,可以看到这样一个常规用法:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:use-pool="true"/>
  <!-- redis template definition -->
  <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnectionFactory"/>
  ...

</beans>
public class Example {

  // inject the actual template
  @Autowired
  private RedisTemplate<String, String> template;

  // inject the template as ListOperations
  @Resource(name="redisTemplate")
  private ListOperations<String, String> listOps;

  public void addLink(String userId, URL url) {
    listOps.leftPush(userId, url.toExternalForm());
  }
}

代码摘自:https://docs.spring.io/spring-data/redis/docs/2.2.5.RELEASE/reference/html/#redis:template

RedisTemplateListOperations 并没有继承关系,这里是怎么将 RedisTemplate 注入到 ListOperations 类型上去的呢?而且不但可以将 RedisTemplate 注入到 ListOperations ,也可以注入到 ValueOperationsSetOperationsZSetOperationsHashOperations 等类型上。

PropertyEditor

Spring 框架可以通过 java.beans.PropertyEditor 接口的实现类来实现类型转换。

Spring Data Redis 提供了 ListOperationsEditor 可以将 RedisTemplate 转为 ListOperations

class ListOperationsEditor extends PropertyEditorSupport {

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

代码摘自:https://github.com/spring-projects/spring-data-redis/blob/2.2.5.RELEASE/src/main/java/org/springframework/data/redis/core/ListOperationsEditor.java

以上代码中,RedisOperationsRedisTemplate 的父级接口,((RedisOperations) value).opsForList() 实际上就是调用 RedisTemplate.opsForList() 获取 ListOperations

Spring 如何注册 PropertyEditor

Note also that the standard JavaBeans infrastructure automatically discovers PropertyEditor classes (without you having to register them explicitly) if they are in the same package as the class they handle and have the same name as that class, with Editor appended. For example, one could have the following class and package structure, which would be sufficient for the SomethingEditor class to be recognized and used as the PropertyEditor for Something-typed properties.

摘自:https://docs.spring.io/spring/docs/5.2.4.RELEASE/spring-framework-reference/core.html#beans-beans-conversion

文档中提到,如果 PropertyEditor 类与它们处理的类在同一个包中,并且类名再加上 Editor 后缀,则无需显式注册,该 PropertyEditor 可以被自动发现。

在 Spring Data Redis 源码中可以看到,ListOperations 类和 ListOperationsEditor 都在 org.springframework.data.redis.core 包下,且 ListOperationsEditor 符合命名规则,即在 ListOperations 类名上加上 Editor 后缀,所以可以自动发现并生效。

谁把谁当真 2022-09-10 19:42:09

看看这个类 ListOperationsEditor

class ListOperationsEditor extends PropertyEditorSupport {

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

利用 PropertyEditorSupport 转换类型 (RedisTemplate -> ListOperations)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文