Spring Cloud @RefreshScope 原理及使用

yizhihongxing

Spring Cloud @RefreshScope 原理及使用

什么是 @RefreshScope

在使用 Spring Cloud 进行应用程序开发时,我们经常会遇到一些需要在应用程序运行时更新的配置参数,比如数据库连接字符串、缓存配置等等。为了避免每次修改这些参数之后需要重启应用程序,我们可以通过使用 Spring Cloud 提供的 @RefreshScope 实现在应用程序运行时动态更新这些参数。

@RefreshScope 是 Spring Cloud 核心组件之一——Spring Cloud Config 提供的一个注解,它可以标记在 Spring 组件类上,用于指示该组件的配置参数可以动态更新。

使用 @RefreshScope 标记的组件,每当变量值发生改变时,都可以利用 Spring Cloud Config 提供的 RefreshEndpoint 实现刷新,该端点可以通过 POST 方式请求调用。

@RefreshScope 的原理

@RefreshScope 的原理是基于 Spring Cloud 基础架构,其基本流程为:

  1. Spring Cloud Config 从配置服务器获取配置参数信息。
  2. 将配置信息注入应用程序中的组件,其中使用了 @RefreshScope 进行标记的组件会被特殊处理,并在注入完成之后加入到更新队列中。
  3. 当 RefreshEndpoint 接收到 POST 请求之后,通过遍历更新队列,重新实例化应用程序中使用了 @RefreshScope 标记的组件,并更新其属性值。

Spring Cloud Config 与 RefreshEndpoint 之间的原理比较复杂,涉及到一些 Spring Cloud 技术体系的核心组件,因此我们在这里不予赘述。

如何使用 @RefreshScope

使用 @RefreshScope 非常简单,只需按照以下步骤即可:

  1. 将需要动态更新的配置参数定义到 application.yml 中。
  2. 开启 @RefreshScope 的功能,需要在应用程序中导入 spring-cloud-context 依赖,并在配置类或主类上添加 @EnableRefreshScope 注解。
  3. 在需要动态更新的组件上添加 @RefreshScope 注解。

示例代码如下:

application.yml 配置文件内容

spring:
  application:
    name: refresh-demo
  cloud:
    config:
      uri: http://localhost:8888
  datasource:
    url: jdbc:mysql://localhost:3306/testdb
    username: root
    password: 123456
server:
  port: 8080

MainApplication.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;

@SpringBootApplication
@EnableDiscoveryClient
public class MainApplication {

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}

ConfigController.java

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RefreshScope
public class ConfigController {

    @Value("${spring.datasource.url}")
    private String url;

    @Value("${spring.datasource.username}")
    private String username;

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

    @GetMapping("/config")
    public String getConfig() {
        return "url: " + url + ", username: " + username + ", password: " + password;
    }
}

通过以上配置,我们就完成了应用程序动态更新配置参数的功能。在启动应用程序后,我们可以通过 POST http://localhost:8080/actuator/refresh 请求来更新配置参数,然后再次请求 http://localhost:8080/config ,就可以看到修改后的配置参数了。

示例2

以上的示例比较简单,只是展示了如何使用 @RefreshScope 动态更新单个配置参数。实际应用中,我们可能还需要更新更多的配置参数,或者需要实现更加复杂的更新逻辑。下面我们来看一个更加复杂的示例。

application.yml 配置文件

这里我们增加了一个配置参数,来测试更新多个参数的情况。

spring:
  application:
    name: refresh-demo
  cloud:
    config:
      uri: http://localhost:8888
  datasource:
    url: jdbc:mysql://localhost:3306/testdb
    username: root
    password: 123456
  redis:
    host: localhost
    port: 6379
    password: null
server:
  port: 8080

MainApplication.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;

@SpringBootApplication
@EnableDiscoveryClient
public class MainApplication {

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}

ConfigController.java

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RefreshScope
public class ConfigController {

    @Value("${spring.datasource.url}")
    private String dataSourceUrl;

    @Value("${spring.datasource.username}")
    private String dataSourceUsername;

    @Value("${spring.datasource.password}")
    private String dataSourcePassword;

    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private int redisPort;

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

    @GetMapping("/config")
    public String getConfig() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("data source url: ").append(dataSourceUrl).append("\n");
        stringBuilder.append("data source username: ").append(dataSourceUsername).append("\n");
        stringBuilder.append("data source password: ").append(dataSourcePassword).append("\n");
        stringBuilder.append("redis host: ").append(redisHost).append("\n");
        stringBuilder.append("redis port: ").append(redisPort).append("\n");
        stringBuilder.append("redis password: ").append(redisPassword).append("\n");
        return stringBuilder.toString();
    }
}

ConfigUpdateListener.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@Component
public class ConfigUpdateListener implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private RefreshScope refreshScope;

    @Autowired
    private ConfigController configController;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        // 由于 RefreshScope 的存在,在监听到 ContextRefreshedEvent 事件时,所有 @RefreshScope 标记的组件都已经被实例化和注入了配置参数,所以可以直接使用
        new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(5_000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 手动触发 @RefreshScope 的更新
                refreshScope.refresh("configController");
                System.out.println("Config updated: " + configController.getConfig());
            }
        }).start();
    }
}

通过以上代码,我们实现了一个配置更新监听器 ConfigUpdateListener,每隔 5 秒钟自动触发 @RefreshScope 的更新,然后输出更新后的数据。与单个配置参数更新不同的是,这里需要手动触发更新并重启组件。

在以上示例中,我们通过配置文件来存储需要动态更新的配置参数,并使用 @RefreshScope 标记了需要进行动态更新的组件。然后通过 RefreshEndpoint 接口来动态更新配置参数。

结论

使用 Spring Cloud @RefreshScope 可以方便地实现应用程序运行时动态更新配置参数的功能。对于需要频繁修改参数的情况,使用 @RefreshScope 可以避免应用程序每次修改参数都需要重启,提高了效率和稳定性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Cloud @RefreshScope 原理及使用 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • CentOS7.x卸载与安装MySQL5.7的操作过程及编码格式的修改方法

    下面是详细的“CentOS7.x卸载与安装MySQL5.7的操作过程及编码格式的修改方法”的完整攻略。 卸载MySQL 在卸载MySQL之前,应该先备份你的MySQL数据,以下是卸载MySQL的步骤: 停止MySQL服务 sudo systemctl stop mysqld.service 卸载MySQL软件 sudo yum remove mysql* 删…

    other 2023年6月20日
    00
  • windows server设置FTP域用户隔离的方法

    下面是详细讲解“Windows Server设置FTP域用户隔离”的攻略: 准备工作 在进行FTP域用户隔离的设置前,需要先做好以下准备工作: 首先需要安装IIS(Web服务器)以及FTP服务器组件。 确保域用户都已创建好,并且分配好每个用户所能访问的文件夹路径。 步骤一:创建FTP站点 在IIS管理器中,右键单击“站点”并选择“添加FTP站点”。 在“添加…

    other 2023年6月27日
    00
  • 禁止在图片上使用右键

    我来为你详细讲解在网站中禁止图片上使用右键的完整攻略。 1. 禁用右键菜单 网页禁止使用右键需要一些 JavaScript,其实主要原理也很简单,就是用JS禁止右键菜单的弹出事件。在网页中使用以下代码就可以实现: document.oncontextmenu = function() { return false; } 这段Javascript代码会在页面加…

    other 2023年6月27日
    00
  • Excel如何设置减少加载项?Excel设置减少加载项教程

    Excel如何设置减少加载项?Excel设置减少加载项教程 如果你经常使用Excel,你可能已经发现Excel启动慢,这通常是因为加载了过多的插件和扩展程序。这篇文章将为你详细介绍如何设置Excel减少加载项,让Excel启动速度更快。 步骤一:打开Excel选项 首先,在Excel的主菜单中选择“文件”>“选项”。这将打开Excel选项对话框。 步骤…

    other 2023年6月25日
    00
  • C语言动态内存管理的原理及实现方法

    C语言动态内存管理的原理及实现方法 动态内存管理是C语言中非常重要的概念,它允许程序在运行时动态地分配和释放内存。本文将详细讲解C语言动态内存管理的原理及实现方法,并提供两个示例说明。 原理 C语言中的动态内存管理是通过以下几个函数来实现的: malloc(size_t size):用于分配指定大小的内存块,并返回指向该内存块的指针。 calloc(size…

    other 2023年7月31日
    00
  • C语言中字符串常用操作总结

    C语言中字符串常用操作总结 1. 什么是字符串? 在C语言中,字符串是指由一串字符组成的字符数组。字符串中每个字符占据一个字节的内存空间,而字符串所占内存的大小则由其中字符的数量决定。我们可以在代码中以以下方式声明字符串: // 使用字符数组来定义一个字符串(字符指针) char str[] = "Hello World!"; // 使用…

    other 2023年6月20日
    00
  • pycharm软件代码配色和字体设置

    以下是“PyCharm软件代码配色和字体设置的完整攻略”的标准markdown格式文本,其中包含两个示例: PyCharm软件代码配色和字体设置的完整攻略 PyCharm是款流行的Python集成开发环境(IDE),提供了丰富的代码配色和字体设置选项,以满足不同用户的求。以下是PyCharm软件代码配色和字体设置的完整攻略。 1. 代码配色设置 PyChar…

    other 2023年5月10日
    00
  • 魔兽世界6.0熊T技能循环详解 各技能详细分析

    魔兽世界6.0熊T技能循环详解 本篇攻略介绍了魔兽世界6.0版本中,熊德国王专精的技能循环。本攻略将详细讲解各个技能的使用方法和优先级,帮助熊德国王在战斗中表现更加出色。 技能优先级 魔兽世界熊德国王专精的技能使用优先级如下: 月火术 野性冲锋 槌击 树皮术 重击 塞纳里奥结界 治疗之触(治疗模式下使用) 技能优先级的设定主要是出于几个方面的考虑,首先月火术…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部