念念不忘
必有回响

利用 Spring 的类型转换器注入List属性

在Spring应用程序中,通常会为每个Spring容器(或ApplicationContext)配置一个ConversionService实例。 Spring会选择该ConversionService,然后在框架需要执行类型转换时使用它。如果未向Spring注册任何ConversionService,则使用原始的基于PropertyEditor的系统。例如,在项目中配置Redis、ElasticSearch时,通常这些服务都是集群部署的。在创建这些bean的实例时,需要将多个节点都配置到项目的properties文件中,通常都如下所示:

spring.elasticsearch.rest.ip-address=10.254.5.102:9200,10.254.5.107:9201,10.254.5.108:9201
redis.cluster.nodes=10.10.100.197:7000,10.10.100.197:7001,10.10.100.197:7002,10.10.100.197:7003,10.10.100.197:7004,10.10.100.197:7005

properties本身是k-v对,解析出来也都是String类型,那么在我们将这些配置注入到XXXConfig中时,我们就需要自己将这些配置通过切割处理:

@Configuration
@PropertySource(value = {"classpath:application.properties"})
public class RedisConfig {
    private final Logger logger = LoggerFactory.getLogger(RedisConfig.class);

    @Value("${redis.cluster.nodes}")
    private String clusterNodes;

    @Value("${redis.password}")
    private String password;

    @Value("${redis.pool.max-active}")
    private Integer maxTotal;

    @Value("${redis.pool.max-idle}")
    private Integer maxIdle;

    @Value("${redis.pool.min-idle}")
    private Integer minIdle;

    @Value("${redis.pool.max-wait}")
    private Integer maxWaitMillis;

    @Value("${redis.testOnBorrow:true}")
    private boolean testOnBorrow;


    /**
     * 创建连接工厂
     *
     * @return
     */
    @Bean(value = "jedisConnectionFactory")
    public JedisConnectionFactory createConnectionFactory() {
        JedisConnectionFactory jedisConnectionFactory = null;
        // 集群模式
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
        // 加载服务器集群节点
        Set serviceRedisNodes = new HashSet<>(Arrays.asList(clusterNodes.split(",")));
        try {
            // 转换成Redis点节
            Set clusterNodes = new HashSet<>(serviceRedisNodes.size());
            for (String node : serviceRedisNodes) {
                String[] ipAndPort = StringUtils.split(node, ":");
                String ip = ipAndPort[0];
                int port = Integer.parseInt(ipAndPort[1]);
                clusterNodes.add(new RedisNode(ip, port));
            }
            redisClusterConfiguration.setClusterNodes(clusterNodes);

            // Redis 连接池配置
            JedisPoolConfig poolConfig = new JedisPoolConfig();
            poolConfig.setMaxIdle(maxIdle);
            poolConfig.setMaxTotal(maxTotal);
            poolConfig.setMinIdle(minIdle);
            poolConfig.setMaxWaitMillis(maxWaitMillis);
            poolConfig.setTestOnBorrow(testOnBorrow);

            // 创建连接工厂
            jedisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration, poolConfig);
            // 设置数据库
            jedisConnectionFactory.setDatabase(0);
            // 设置密码
            jedisConnectionFactory.setPassword(password);
        } catch (Exception e) {
            logger.error("创建Redis连接工厂错误:{}", e);
        }
        return jedisConnectionFactory;
    }

    @Bean(value = "redisTemplate")
    public RedisTemplate<String, Object> registerRedisTemplate(JedisConnectionFactory jedisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(jedisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.setValueSerializer(new FastJson2JsonRedisSerializer<>(Object.class));
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        //redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashValueSerializer(new FastJson2JsonRedisSerializer<>(Object.class));
        return redisTemplate;
    }
}

这里创建Jedis实例的时候就是通过自己处理的参数。虽然三两行代码就能搞定,但也麻烦,直接将其注入为List岂不更好?

@Value("${redis.cluster.nodes}")
private List<String> clusterNodes;

当然,如果你直接这样注入是不行的,还需要Spring的一个类型转换器org.springframework.context.support.ConversionServiceFactoryBean。在applicationContext.xml中配置如下的bean:

<bean id="conversionService"
      class="org.springframework.context.support.ConversionServiceFactoryBean" />

此时便可以注入成功了。

赞(0) 打赏
未经允许不得转载:码农志 » 利用 Spring 的类型转换器注入List属性

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏