spring.factories
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
RedisAutoConfiguration
- package org.springframework.boot.autoconfigure.data.redis;
-
-
- @Configuration(
- proxyBeanMethods = false
- )
- @ConditionalOnClass({RedisOperations.class})
- @EnableConfigurationProperties({RedisProperties.class}) //自动配置properties 文件
- @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
- public class RedisAutoConfiguration {
- public RedisAutoConfiguration() {
- }
-
- @Bean
- @ConditionalOnMissingBean(
- name = {"redisTemplate"}
- )
- @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
- public RedisTemplate
- RedisTemplate
- template.setConnectionFactory(redisConnectionFactory);
- return template;
- }
-
- @Bean
- @ConditionalOnMissingBean
- @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
- public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
- return new StringRedisTemplate(redisConnectionFactory);
- }
- }
LettuceConnectionConfiguration
- package org.springframework.boot.autoconfigure.data.redis;
-
- @Configuration(
- proxyBeanMethods = false
- )
- @ConditionalOnClass({RedisClient.class})
- @ConditionalOnProperty(
- name = {"spring.redis.client-type"},
- havingValue = "lettuce",
- matchIfMissing = true
- )
- class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
- LettuceConnectionConfiguration(RedisProperties properties, ObjectProvider
standaloneConfigurationProvider, ObjectProvider sentinelConfigurationProvider, ObjectProvider clusterConfigurationProvider) { - super(properties, standaloneConfigurationProvider, sentinelConfigurationProvider, clusterConfigurationProvider);
- }
-
- //使用ObjectProvider
进行构造器注入,将ioc 中的对象注入到这里 - @Bean(
- destroyMethod = "shutdown"
- )
- @ConditionalOnMissingBean({ClientResources.class})
- DefaultClientResources lettuceClientResources(ObjectProvider
customizers) { - Builder builder = DefaultClientResources.builder();
- customizers.orderedStream().forEach((customizer) -> {
- customizer.customize(builder);
- });
- return builder.build();
- }
-
- // 创建RedisConnectionFactory并注入到容器
- @Bean
- @ConditionalOnMissingBean({RedisConnectionFactory.class})
- LettuceConnectionFactory redisConnectionFactory(ObjectProvider
builderCustomizers, ClientResources clientResources) { - // 获取lettuce客户端配置(获取配置逻辑在下面)
- LettuceClientConfiguration clientConfig = this.getLettuceClientConfiguration(builderCustomizers, clientResources, this.getProperties().getLettuce().getPool());
-
- return this.createLettuceConnectionFactory(clientConfig); //创建lettuce
- }
-
- //根据配置文件不同,创建不同的连接工厂,如果配置是哨兵则创建哨兵模式的连接工厂,如果是集群则创建集群的连接工厂,如果是单点则创建单点的连接工厂
- private LettuceConnectionFactory createLettuceConnectionFactory(LettuceClientConfiguration clientConfiguration) {
- if (this.getSentinelConfig() != null) {
- //创建哨兵模式的连接工厂
- return new LettuceConnectionFactory(this.getSentinelConfig(), clientConfiguration);
- } else {
-
- return this.getClusterConfiguration() != null ? new LettuceConnectionFactory(this.getClusterConfiguration(), clientConfiguration) : new LettuceConnectionFactory(this.getStandaloneConfig(), clientConfiguration);
- }
- }
-
- // 构建lettuce客户端连接配置
- private LettuceClientConfiguration getLettuceClientConfiguration(ObjectProvider
builderCustomizers, ClientResources clientResources, Pool pool) { - // lettuce客户端配置建造者,通过建造者去解析url、连接主机、端口等信息,然后构建成一个lettuce客户端配置
- LettuceClientConfigurationBuilder builder = this.createBuilder(pool);
- this.applyProperties(builder);
- if (StringUtils.hasText(this.getProperties().getUrl())) {
- this.customizeConfigurationFromUrl(builder);
- }
-
- builder.clientOptions(this.createClientOptions());
- builder.clientResources(clientResources);
- builderCustomizers.orderedStream().forEach((customizer) -> {
- customizer.customize(builder);
- });
- return builder.build();
- }
-
- private LettuceClientConfigurationBuilder createBuilder(Pool pool) {
- return this.isPoolEnabled(pool) ? (new LettuceConnectionConfiguration.PoolBuilderFactory()).createBuilder(pool) : LettuceClientConfiguration.builder();
- }
-
- private LettuceClientConfigurationBuilder applyProperties(LettuceClientConfigurationBuilder builder) {
- if (this.getProperties().isSsl()) {
- builder.useSsl();
- }
-
- if (this.getProperties().getTimeout() != null) {
- builder.commandTimeout(this.getProperties().getTimeout());
- }
-
- if (this.getProperties().getLettuce() != null) {
- Lettuce lettuce = this.getProperties().getLettuce();
- if (lettuce.getShutdownTimeout() != null && !lettuce.getShutdownTimeout().isZero()) {
- builder.shutdownTimeout(this.getProperties().getLettuce().getShutdownTimeout());
- }
- }
-
- if (StringUtils.hasText(this.getProperties().getClientName())) {
- builder.clientName(this.getProperties().getClientName());
- }
-
- return builder;
- }
-
- private ClientOptions createClientOptions() {
- io.lettuce.core.ClientOptions.Builder builder = this.initializeClientOptionsBuilder();
- Duration connectTimeout = this.getProperties().getConnectTimeout();
- if (connectTimeout != null) {
- builder.socketOptions(SocketOptions.builder().connectTimeout(connectTimeout).build());
- }
- return builder.timeoutOptions(TimeoutOptions.enabled()).build();
- }
-
- private io.lettuce.core.ClientOptions.Builder initializeClientOptionsBuilder() {
- if (this.getProperties().getCluster() != null) {
- io.lettuce.core.cluster.ClusterClientOptions.Builder builder = ClusterClientOptions.builder();
- Refresh refreshProperties = this.getProperties().getLettuce().getCluster().getRefresh();
- io.lettuce.core.cluster.ClusterTopologyRefreshOptions.Builder refreshBuilder = ClusterTopologyRefreshOptions.builder().dynamicRefreshSources(refreshProperties.isDynamicRefreshSources());
- if (refreshProperties.getPeriod() != null) {
- refreshBuilder.enablePeriodicRefresh(refreshProperties.getPeriod());
- }
-
- if (refreshProperties.isAdaptive()) {
- refreshBuilder.enableAllAdaptiveRefreshTriggers();
- }
-
- return builder.topologyRefreshOptions(refreshBuilder.build());
- } else {
- return ClientOptions.builder();
- }
- }
-
- private void customizeConfigurationFromUrl(LettuceClientConfigurationBuilder builder) {
- ConnectionInfo connectionInfo = this.parseUrl(this.getProperties().getUrl());
- if (connectionInfo.isUseSsl()) {
- builder.useSsl();
- }
- }
-
- private static class PoolBuilderFactory {
- private PoolBuilderFactory() {
- }
-
- LettuceClientConfigurationBuilder createBuilder(Pool properties) {
- return LettucePoolingClientConfiguration.builder().poolConfig(this.getPoolConfig(properties));
- }
-
- private GenericObjectPoolConfig> getPoolConfig(Pool properties) {
- GenericObjectPoolConfig> config = new GenericObjectPoolConfig();
- config.setMaxTotal(properties.getMaxActive());
- config.setMaxIdle(properties.getMaxIdle());
- config.setMinIdle(properties.getMinIdle());
- if (properties.getTimeBetweenEvictionRuns() != null) {
- config.setTimeBetweenEvictionRuns(properties.getTimeBetweenEvictionRuns());
- }
-
- if (properties.getMaxWait() != null) {
- config.setMaxWait(properties.getMaxWait());
- }
-
- return config;
- }
- }
- }
RedisProperties
- package org.springframework.boot.autoconfigure.data.redis;
-
- @ConfigurationProperties(
- prefix = "spring.redis"
- ) //加载前缀为spring.redis 的配置信息
- public class RedisProperties {
- private int database = 0;
- private String url;
- private String host = "localhost";
- private String username;
- private String password;
- private int port = 6379;
- private boolean ssl;
- private Duration timeout;
- private Duration connectTimeout;
- private String clientName;
- private RedisProperties.ClientType clientType;
- private RedisProperties.Sentinel sentinel;
- private RedisProperties.Cluster cluster;
- private final RedisProperties.Jedis jedis = new RedisProperties.Jedis();
- private final RedisProperties.Lettuce lettuce = new RedisProperties.Lettuce();
-
- public RedisProperties() {
- }
-
- public static class Lettuce {
- private Duration shutdownTimeout = Duration.ofMillis(100L);
- private final RedisProperties.Pool pool = new RedisProperties.Pool();
- private final RedisProperties.Lettuce.Cluster cluster = new RedisProperties.Lettuce.Cluster();
-
- public Lettuce() {
- }
-
- public Duration getShutdownTimeout() {
- return this.shutdownTimeout;
- }
-
- public void setShutdownTimeout(Duration shutdownTimeout) {
- this.shutdownTimeout = shutdownTimeout;
- }
-
- public RedisProperties.Pool getPool() {
- return this.pool;
- }
-
- public RedisProperties.Lettuce.Cluster getCluster() {
- return this.cluster;
- }
-
- public static class Cluster {
- private final RedisProperties.Lettuce.Cluster.Refresh refresh = new RedisProperties.Lettuce.Cluster.Refresh();
-
- public Cluster() {
- }
-
- public RedisProperties.Lettuce.Cluster.Refresh getRefresh() {
- return this.refresh;
- }
-
- public static class Refresh {
- private boolean dynamicRefreshSources = true;
- private Duration period;
- private boolean adaptive;
- public Refresh() {
- }
-
- public boolean isDynamicRefreshSources() {
- return this.dynamicRefreshSources;
- }
-
- public void setDynamicRefreshSources(boolean dynamicRefreshSources) {
- this.dynamicRefreshSources = dynamicRefreshSources;
- }
-
- public Duration getPeriod() {
- return this.period;
- }
-
- public void setPeriod(Duration period) {
- this.period = period;
- }
-
- public boolean isAdaptive() {
- return this.adaptive;
- }
-
- public void setAdaptive(boolean adaptive) {
- this.adaptive = adaptive;
- }
- }
- }
- }
-
- public static class Jedis {
- private final RedisProperties.Pool pool = new RedisProperties.Pool();
- public Jedis() {
- }
-
- public RedisProperties.Pool getPool() {
- return this.pool;
- }
- }
-
- public static class Sentinel {
- private String master;
- private List
nodes; - private String password;
-
- public Sentinel() {
- }
-
- public String getMaster() {
- return this.master;
- }
-
- public void setMaster(String master) {
- this.master = master;
- }
-
- public List
getNodes() { - return this.nodes;
- }
-
- public void setNodes(List
nodes) { - this.nodes = nodes;
- }
-
- public String getPassword() {
- return this.password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
- }
-
- public static class Cluster {
- private List
nodes; - private Integer maxRedirects;
-
- public Cluster() {
- }
-
- public List
getNodes() { - return this.nodes;
- }
-
- public void setNodes(List
nodes) { - this.nodes = nodes;
- }
-
- public Integer getMaxRedirects() {
- return this.maxRedirects;
- }
-
- public void setMaxRedirects(Integer maxRedirects) {
- this.maxRedirects = maxRedirects;
- }
- }
-
- public static class Pool {
- private Boolean enabled;
- private int maxIdle = 8;
- private int minIdle = 0;
- private int maxActive = 8;
- private Duration maxWait = Duration.ofMillis(-1L);
- private Duration timeBetweenEvictionRuns;
-
- public Pool() {
- }
-
- public Boolean getEnabled() {
- return this.enabled;
- }
-
- public void setEnabled(Boolean enabled) {
- this.enabled = enabled;
- }
-
- public int getMaxIdle() {
- return this.maxIdle;
- }
-
- public void setMaxIdle(int maxIdle) {
- this.maxIdle = maxIdle;
- }
-
- public int getMinIdle() {
- return this.minIdle;
- }
-
- public void setMinIdle(int minIdle) {
- this.minIdle = minIdle;
- }
-
- public int getMaxActive() {
- return this.maxActive;
- }
-
- public void setMaxActive(int maxActive) {
- this.maxActive = maxActive;
- }
-
- public Duration getMaxWait() {
- return this.maxWait;
- }
-
- public void setMaxWait(Duration maxWait) {
- this.maxWait = maxWait;
- }
-
- public Duration getTimeBetweenEvictionRuns() {
- return this.timeBetweenEvictionRuns;
- }
-
- public void setTimeBetweenEvictionRuns(Duration timeBetweenEvictionRuns) {
- this.timeBetweenEvictionRuns = timeBetweenEvictionRuns;
- }
- }
-
- public static enum ClientType {
- LETTUCE,
- JEDIS;
-
-
- private ClientType() {
- }
- }
- }
类图解析:
类名 | 类信息说明 |
RedisStandaloneConfiguration | redis单点配置 |
RedisSentinelConfiguration | redis 哨兵配置 |
RedisClusterConfiguration | redis集群配置 |
RedisProperties | redis属性文件文件配置类,从配置文件中读取属性文件,写入配置类中 |
RedisConnectionConfiguration | redis连接配置,是lettuce连接和jedis连接配置的抽象父类,封装了redis的各种配置方式 |
LettuceConnectionConfiguration | lettuce 客户端配置 |
JedisConnectionConfiguration | jedis客户端配置 |
RedisAutoConfiguration | springboot 中 redis的自动配置类 |
redis自动配置类加载时序图:
流程图解析:
②RedisConnectionConfiguration 构造方法调用
- //为redis配置赋值
- protected RedisConnectionConfiguration(RedisProperties properties, ObjectProvider
standaloneConfigurationProvider, ObjectProvider sentinelConfigurationProvider, ObjectProvider clusterConfigurationProvider) { - this.properties = properties;
- this.standaloneConfiguration = (RedisStandaloneConfiguration)standaloneConfigurationProvider.getIfAvailable();
- this.sentinelConfiguration = (RedisSentinelConfiguration)sentinelConfigurationProvider.getIfAvailable();
- this.clusterConfiguration = (RedisClusterConfiguration)clusterConfigurationProvider.getIfAvailable();
- }
解析,当RedisConnectionConfiguration的构造方法被子类LettuceConnectionConfiguration调用时,会为RedisProperties、RedisClusterConfiguration、RedisSentinelConfiguration、RedisStandaloneConfiguration这几个配置属性赋值。
⑤LettuceConnectionConfiguration 创建连接工厂
- //根据配置文件不同,创建不同的连接工厂,如果配置是哨兵则创建哨兵模式的连接工厂,如果是集群则创建集群的连接工厂,如果是单点则创建单点的连接工厂
- private LettuceConnectionFactory createLettuceConnectionFactory(LettuceClientConfiguration clientConfiguration) {
- if (this.getSentinelConfig() != null) {
- //创建哨兵模式的连接工厂
- return new LettuceConnectionFactory(this.getSentinelConfig(), clientConfiguration);
- } else {
-
- return this.getClusterConfiguration() != null ? new LettuceConnectionFactory(this.getClusterConfiguration(), clientConfiguration) : new LettuceConnectionFactory(this.getStandaloneConfig(), clientConfiguration);
- }
- }
解析:当createLettuceConnectionFactory()方法被调用时,会根据RedisConnectionConfiguration构造方法中对redis的配置初始化情况,选择配置对象不为空的配置对象创建连接工厂
项目连接集群配置示例:
- #redis 配置
- redis:
- database: 1
- lettuce:
- pool:
- max-active: 3000 #最大连接数据库连接数,设 -1 为没有限制
- max-idle: 3000 #最大等待连接中的数量,设 0 为没有限制
- max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
- min-idle: 0 #最小等待连接中的数量,设 0 为没有限制
- shutdown-timeout: 100ms
- password: xxxxxx
- #standalone 使用此配置
- #host: 10.1.x.xxx
- #port: 6379
- #cluster 使用此配置
- cluster:
- timeout: 5000
- max-redirects: 3
- nodes:
- - 10.2.6.xx:6379
- - 10.2.6.xx:6380
- - 10.2.6.xx:6381
- - 10.2.6.xx:6382
- - 10.2.6.xx:6383
- - 10.2.6.xx:6384