在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" />
此时便可以注入成功了。