Spring Cloud @RefreshScope 原理及使用

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日

相关文章

  • vueCli4如何配置vue.config.js文件

    下面是vueCli4 如何配置 vue.config.js 文件的攻略: 创建 vue.config.js 在项目根目录下创建 vue.config.js 文件。 配置 vue.config.js 打开 vue.config.js,添加需要配置的选项,比如 publicPath、outputDir 等等。 module.exports = { publicP…

    other 2023年6月27日
    00
  • Win11电脑进程怎么设置优先级别?Win11任务管理器设置进程优先级别方法

    Win11电脑进程怎么设置优先级别? 在Win11操作系统中,可以使用任务管理器来设置进程的优先级别。通过设置进程的优先级别,可以影响系统对进程的资源分配和执行顺序。下面是设置进程优先级别的方法: 方法一:使用任务管理器设置进程优先级别 打开任务管理器:通过右键点击任务栏空白处,选择”任务管理器”,或者按下“Ctrl + Shift + Esc”组合键直接打…

    other 2023年6月28日
    00
  • XShell免费版的安装配置教程及使用保姆级教程

    XShell免费版安装配置教程及使用保姆级教程 安装 下载XShell免费版安装包 前往XShell官网下载XShell免费版的安装包。 安装XShell 打开下载的安装包,按照提示完成XShell的安装。 配置 创建一个新的会话 在XShell的菜单栏中选择文件->新建->会话。 在弹出的窗口中,输入远程主机的连接信息,包括主机名、端口号、登录…

    other 2023年6月27日
    00
  • java 抽象类的实例详解

    Java 抽象类的实例详解 什么是抽象类? 抽象类是一种不能实例化的类,它为其他类提供了一种通用的抽象概念。抽象类可以包含抽象方法和非抽象方法。抽象方法只有方法名,没有具体的实现,而非抽象方法有具体的实现。 抽象类通过关键字abstract来声明。抽象方法必须在抽象类中声明,而非抽象方法不一定要在抽象类中声明。 抽象类的定义与实现 定义抽象类的基本语法为: …

    other 2023年6月27日
    00
  • javascrip关于继承的小例子

    我们来详细讲解一下“JavaScript关于继承的小例子”的完整攻略。 基本概念 在 JavaScript 中,继承是一种重要的功能,它允许我们通过创建一个新对象来扩展已有的对象。通过继承,我们可以避免重复编写相同的代码,提高代码复用性,同时也可以提高程序的灵活性。 JavaScript 中的继承实现方式有很多种,其中最常见的两种方式是原型链继承和类继承。 …

    other 2023年6月27日
    00
  • iOS10推送通知开发教程

    iOS10推送通知开发教程 1. 概述 推送通知是iOS应用中一种重要的功能,它可以让应用在后台或锁屏状态下向用户发送通知消息。本教程将详细介绍如何在iOS10中进行推送通知的开发。 2. 准备工作 在开始开发之前,你需要准备以下内容:- 一台Mac电脑- 最新版本的Xcode开发环境- 有效的Apple开发者账号 3. 创建证书和配置推送服务 在进行推送通…

    other 2023年6月28日
    00
  • android项目从Eclipse迁移到Android studio中常见问题解决方法

    以下是将Android项目从Eclipse迁移到Android Studio中常见问题解决方法的完整攻略: 问题1:导入项目后无法找到R类 解决方法:- 确保您的项目中没有任何编译错误。如果有错误,请先解决它们。- 确保您的项目中存在res文件夹,并且其中包含正确的资源文件。- 清理并重新构建项目。在Android Studio的菜单栏中选择Build -&…

    other 2023年10月16日
    00
  • 详解ASP.NET七大身份验证方式以及解决方案

    详解ASP.NET七大身份验证方式以及解决方案 身份验证的概念 身份验证是指在网络环境下确认用户身份和权限的技术。在Web应用程序中,身份验证是保护数据和其他私密或机密资源的第一道防线。ASP.NET提供了丰富的身份验证方式和解决方案,帮助开发人员轻易地实现各种需求。 Forms身份验证 Forms身份验证是ASP.NET提供的最基本的身份验证方式。它的工作…

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