redisson-spring-boot-starter 自动化配置源码解析

这篇具有很好参考价值的文章主要介绍了redisson-spring-boot-starter 自动化配置源码解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

版本

redisson-spring-boot-starter:3.25.2

此starter会自动注册RedissonClient Bean
并可通过注册RedissonAutoConfigurationCustomizer Bean实现配置自定义

 @Bean
 RedissonAutoConfigurationCustomizer jdkCodecCustomizer() {
     return configuration->{
         // 使用JDK序列化器
         configuration.setCodec(new SerializationCodec());
     };
 }

源码

spring-boot:2.7以上
org.redisson.spring.starter.RedissonAutoConfigurationV2

@AutoConfiguration(before = RedisAutoConfiguration.class)
@ConditionalOnClass({Redisson.class, RedisOperations.class})
@EnableConfigurationProperties({RedissonProperties.class, RedisProperties.class}) // 启用spring.data.redis,spring.redisson配置属性
public class RedissonAutoConfigurationV2 extends RedissonAutoConfiguration {
}

spring-boot:2.6以下
org.redisson.spring.starter.RedissonAutoConfiguration文章来源地址https://www.toymoban.com/news/detail-797395.html

@Configuration
@ConditionalOnClass({Redisson.class, RedisOperations.class})
// 防止spring-boot:2.7以上版本时跟RedissonAutoConfigurationV2冲突
@ConditionalOnMissingClass("org.springframework.boot.autoconfigure.AutoConfiguration") 
@AutoConfigureBefore(RedisAutoConfiguration.class)
@EnableConfigurationProperties({RedissonProperties.class, RedisProperties.class})
public class RedissonAutoConfiguration {
	...
	// 注册RedissonClient 
	@Bean(destroyMethod = "shutdown")
    @ConditionalOnMissingBean(RedissonClient.class)
    public RedissonClient redisson() throws IOException {
        Config config;
        Method clusterMethod = ReflectionUtils.findMethod(RedisProperties.class, "getCluster");
        Method usernameMethod = ReflectionUtils.findMethod(RedisProperties.class, "getUsername");
        Method timeoutMethod = ReflectionUtils.findMethod(RedisProperties.class, "getTimeout");
        Method connectTimeoutMethod = ReflectionUtils.findMethod(RedisProperties.class, "getConnectTimeout");
        Method clientNameMethod = ReflectionUtils.findMethod(RedisProperties.class, "getClientName");

        Object timeoutValue = ReflectionUtils.invokeMethod(timeoutMethod, redisProperties);
        String prefix = getPrefix();

        String username = null;
        int database = redisProperties.getDatabase();
        String password = redisProperties.getPassword();
        boolean isSentinel = false;
        boolean isCluster = false;
        // 如果存在redis连接详细配置,则从详细配置中获取用户名,密码,哨兵模式标识,集群模式标识
        if (hasConnectionDetails()) {
            ObjectProvider<RedisConnectionDetails> provider = ctx.getBeanProvider(RedisConnectionDetails.class);
            RedisConnectionDetails b = provider.getIfAvailable();
            if (b != null) {
                password = b.getPassword();
                username = b.getUsername();

                if (b.getSentinel() != null) {
                    isSentinel = true;
                }
                if (b.getCluster() != null) {
                    isCluster = true;
                }
            }
        }
		// 获取redis配置中的超时时间
        Integer timeout = null;
        if (timeoutValue instanceof Duration) {
            timeout = (int) ((Duration) timeoutValue).toMillis();
        } else if (timeoutValue != null){
            timeout = (Integer)timeoutValue;
        }
		// 获取redis配置中的连接超时时间
        Integer connectTimeout = null;
        if (connectTimeoutMethod != null) {
            Object connectTimeoutValue = ReflectionUtils.invokeMethod(connectTimeoutMethod, redisProperties);
            if (connectTimeoutValue != null) {
                connectTimeout = (int) ((Duration) connectTimeoutValue).toMillis();
            }
        } else {
            connectTimeout = timeout;
        }
		// 获取redis配置中的客户端名称
        String clientName = null;
        if (clientNameMethod != null) {
            clientName = (String) ReflectionUtils.invokeMethod(clientNameMethod, redisProperties);
        }
		// 获取redis配置中的用户名
        if (usernameMethod != null) {
            username = (String) ReflectionUtils.invokeMethod(usernameMethod, redisProperties);
        }
		if (redissonProperties.getConfig() != null) {
            // 如果存在redisson配置(在application.yml中以字符串形式配置)
        	try {
            	// 尝试解析yml格式配置字符串
                config = Config.fromYAML(redissonProperties.getConfig());
            } catch (IOException e) {
                try {
                	// 尝试解析json格式配置字符串
                    config = Config.fromJSON(redissonProperties.getConfig());
                } catch (IOException e1) {
                    e1.addSuppressed(e);
                    throw new IllegalArgumentException("Can't parse config", e1);
                }
            }
        } else if (redissonProperties.getFile() != null) {
        	// 如果存在redisson配置文件(yml或json)
            try {
                InputStream is = getConfigStream();
                config = Config.fromYAML(is);
            } catch (IOException e) {
                // trying next format
                try {
                    InputStream is = getConfigStream();
                    config = Config.fromJSON(is);
                } catch (IOException e1) {
                    e1.addSuppressed(e);
                    throw new IllegalArgumentException("Can't parse config", e1);
                }
            }
        } else if (redisProperties.getSentinel() != null || isSentinel) {
        	// 连接哨兵模式集群
            String[] nodes = {};
            String sentinelMaster = null;

            if (redisProperties.getSentinel() != null) {
                Method nodesMethod = ReflectionUtils.findMethod(Sentinel.class, "getNodes");
                Object nodesValue = ReflectionUtils.invokeMethod(nodesMethod, redisProperties.getSentinel());
                if (nodesValue instanceof String) {
                    nodes = convert(prefix, Arrays.asList(((String)nodesValue).split(",")));
                } else {
                    nodes = convert(prefix, (List<String>)nodesValue);
                }
                sentinelMaster = redisProperties.getSentinel().getMaster();
            }


            String sentinelUsername = null;
            String sentinelPassword = null;
            if (hasConnectionDetails()) {
                ObjectProvider<RedisConnectionDetails> provider = ctx.getBeanProvider(RedisConnectionDetails.class);
                RedisConnectionDetails b = provider.getIfAvailable();
                if (b != null && b.getSentinel() != null) {
                    database = b.getSentinel().getDatabase();
                    sentinelMaster = b.getSentinel().getMaster();
                    nodes = convertNodes(prefix, (List<Object>) (Object) b.getSentinel().getNodes());
                    sentinelUsername = b.getSentinel().getUsername();
                    sentinelPassword = b.getSentinel().getPassword();
                }
            }

            config = new Config();
            SentinelServersConfig c = config.useSentinelServers()
                    .setMasterName(sentinelMaster)
                    .addSentinelAddress(nodes)
                    .setSentinelPassword(sentinelPassword)
                    .setSentinelUsername(sentinelUsername)
                    .setDatabase(database)
                    .setUsername(username)
                    .setPassword(password)
                    .setClientName(clientName);
            if (connectTimeout != null) {
                c.setConnectTimeout(connectTimeout);
            }
            if (connectTimeoutMethod != null && timeout != null) {
                c.setTimeout(timeout);
            }
            initSSL(c);
        } else if ((clusterMethod != null && ReflectionUtils.invokeMethod(clusterMethod, redisProperties) != null)
                    || isCluster) {
			// 连接分片集群
            String[] nodes = {};
            if (clusterMethod != null && ReflectionUtils.invokeMethod(clusterMethod, redisProperties) != null) {
                Object clusterObject = ReflectionUtils.invokeMethod(clusterMethod, redisProperties);
                Method nodesMethod = ReflectionUtils.findMethod(clusterObject.getClass(), "getNodes");
                List<String> nodesObject = (List) ReflectionUtils.invokeMethod(nodesMethod, clusterObject);

                nodes = convert(prefix, nodesObject);
            }

            if (hasConnectionDetails()) {
                ObjectProvider<RedisConnectionDetails> provider = ctx.getBeanProvider(RedisConnectionDetails.class);
                RedisConnectionDetails b = provider.getIfAvailable();
                if (b != null && b.getCluster() != null) {
                    nodes = convertNodes(prefix, (List<Object>) (Object) b.getCluster().getNodes());
                }
            }

            config = new Config();
            ClusterServersConfig c = config.useClusterServers()
                    .addNodeAddress(nodes)
                    .setUsername(username)
                    .setPassword(password)
                    .setClientName(clientName);
            if (connectTimeout != null) {
                c.setConnectTimeout(connectTimeout);
            }
            if (connectTimeoutMethod != null && timeout != null) {
                c.setTimeout(timeout);
            }
            initSSL(c);
        } else {
        	// 连接单实例
            config = new Config();

            String singleAddr = prefix + redisProperties.getHost() + ":" + redisProperties.getPort();

            if (hasConnectionDetails()) {
                ObjectProvider<RedisConnectionDetails> provider = ctx.getBeanProvider(RedisConnectionDetails.class);
                RedisConnectionDetails b = provider.getIfAvailable();
                if (b != null && b.getStandalone() != null) {
                    database = b.getStandalone().getDatabase();
                    singleAddr = prefix + b.getStandalone().getHost() + ":" + b.getStandalone().getPort();
                }
            }

            SingleServerConfig c = config.useSingleServer()
                    .setAddress(singleAddr)
                    .setDatabase(database)
                    .setUsername(username)
                    .setPassword(password)
                    .setClientName(clientName);
            if (connectTimeout != null) {
                c.setConnectTimeout(connectTimeout);
            }
            if (connectTimeoutMethod != null && timeout != null) {
                c.setTimeout(timeout);
            }
            initSSL(c);
        }
        // 应用自定义配置bean
        if (redissonAutoConfigurationCustomizers != null) {
            for (RedissonAutoConfigurationCustomizer customizer : redissonAutoConfigurationCustomizers) {
                customizer.customize(config);
            }
        }
        return Redisson.create(config);
    }

    private void initSSL(BaseConfig<?> config) {
        Method getSSLMethod = ReflectionUtils.findMethod(RedisProperties.class, "getSsl");
        if (getSSLMethod == null) {
            return;
        }

        RedisProperties.Ssl ssl = redisProperties.getSsl();
        if (ssl.getBundle() == null) {
            return;
        }

        ObjectProvider<SslBundles> provider = ctx.getBeanProvider(SslBundles.class);
        SslBundles bundles = provider.getIfAvailable();
        if (bundles == null) {
            return;
        }
        SslBundle b = bundles.getBundle(ssl.getBundle());
        if (b == null) {
            return;
        }
        config.setSslCiphers(b.getOptions().getCiphers());
        config.setSslProtocols(b.getOptions().getEnabledProtocols());
        config.setSslTrustManagerFactory(b.getManagers().getTrustManagerFactory());
        config.setSslKeyManagerFactory(b.getManagers().getKeyManagerFactory());
    }
}

到了这里,关于redisson-spring-boot-starter 自动化配置源码解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【Spring Boot 3】【Redis】集成Redisson

    软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术总是要花费或多或少的时间、检索不止一篇资料才能得出一个可工作的DEMO,这占用了我大量的时

    2024年01月23日
    浏览(46)
  • Spring Boot Starter Parent

    Spring Boot Starter Parent

    在这,您将学习了解 Spring Boot Starter Parent, 它是 Spring Boot 提供的父级 Pom 文件,旨在提供自动版本依赖管理,帮助我们轻松快速地进行 Spring Boot 开发。 通过 Spring Boot Starter Parent, 我们可以进行简单便捷地包依赖管理。在 Spring Boot 每一个发行版中, 均提供了该版本所兼容的依

    2024年02月08日
    浏览(9)
  • 自定义Spring Boot Starter

    自定义Spring Boot Starter

    Spring Boot starter 我们知道Spring Boot大大简化了项目初始搭建以及开发过程,而这些都是通过Spring Boot提供的starter来完成的。在实际项目中一些基础模块其本质就是starter,所以我们需要对Spring Boot的starter有一个全面深入的了解,这是我们的必备知识。 starter介绍 spring boot 在配置

    2024年02月10日
    浏览(12)
  • Spring Boot Starter设计实现

    Starter 是 Spring Boot 非常重要的一个硬核功能。 通过 Starter 我们可以快速的引入一个功能或模块,而无须关心模块依赖的其它组件。关于配置,Spring Boot 采用“约定大于配置”的设计理念,Starter 一般都会提供默认配置,只有当我们有特殊需求的时候,才需要在 application.yaml 里

    2024年01月18日
    浏览(12)
  • 6. Spring Boot的starters

    6. Spring Boot的starters

    6. Spring Boot的starters(重要) 一般认为,SpringBoot 微框架从两个主要层面影响 Spring 社区的开发者们: 基于 Spring 框架的“约定优先于配置(COC)”理念以及最佳实践之路。 提供了针对日常企业应用研发各种场景的 spring-boot-starter 自动配置依赖模块,如此多“开箱即用”的依赖模

    2024年01月24日
    浏览(15)
  • Spring Boot 集成 Redisson分布式锁

    Spring Boot 集成 Redisson分布式锁

            Redisson 是一种基于 Redis 的 Java 驻留集群的分布式对象和服务库,可以为我们提供丰富的分布式锁和线程安全集合的实现。在 Spring Boot 应用程序中使用 Redisson 可以方便地实现分布式应用程序的某些方面,例如分布式锁、分布式集合、分布式事件发布和订阅等。本篇

    2024年02月10日
    浏览(19)
  • shiro-spring-boot-starter针对不同Spring Boot版本

    对于Spring Boot 2.4.10,无法找到shiro-spring-boot-starter的2.7.2版本,这是一个错误的版本号。 shiro-spring-boot-starter针对不同Spring Boot版本,推荐使用的版本如下: Spring Boot 1.x - 使用版本1.4.1 Spring Boot 2.0.x - 使用版本1.5.3 Spring Boot 2.1.x - 使用版本1.6.0 Spring Boot 2.2.x - 使用版本1.7.0 Spring Boot 2.3

    2024年02月13日
    浏览(10)
  • 自定义 Spring Boot Starter 组件

    自定义 Spring Boot Starter 组件是为了封装和简化特定功能的配置和集成,让用户能够更容易地集成你提供的库或功能。Spring Boot Starter 组件通常包括自动配置、依赖管理和必要的配置。 下面是创建一个简单的 Spring Boot Starter 的基本步骤: 步骤: 创建一个新的 Maven 或 Gradle 项目

    2024年02月05日
    浏览(15)
  • 【Spring Boot 初识丨三】starter

    【Spring Boot 初识丨三】starter

    上一篇讲了如何构建 MAVEN 项目 本篇来讲一讲 starter 依赖项 Spring Boot 初识: 【Spring Boot 初识丨一】入门实战 【Spring Boot 初识丨二】maven 【Spring Boot 初识丨三】starter 【Spring Boot 初识丨四】主应用类   启动器是一组方便的依赖关系描述符,它包含了一系列可以集成到应用里

    2024年02月09日
    浏览(9)
  • Spring Boot Starter介绍和实战

    Spring Boot Starter 是 Spring Boot 提供的一种机制,用于简化和集成应用程序的依赖管理。通过创建自定义的 Starter,可以将一组相关的依赖打包成一个简单的、可重用的模块,使应用程序的配置和依赖管理更加方便。在本文中,我们将深入探讨 Spring Boot Starter 的原理、创建过程,

    2024年01月23日
    浏览(10)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包