手写分布式配置中心(五)整合springboot(不自动刷新的)

news2025/3/1 15:53:52

springboot中使用配置方式有四种,分别是environment、BeanDefinition、@Value、@ConfigurationProperties。具体的原理可以看我之前的一篇文章https://blog.csdn.net/cjc000/article/details/132800290。代码在https://gitee.com/summer-cat001/config-center

原理

environment是存储配置的地方,其他的都是从这里获取的数据。所以只要在他们用到配置之前,把配置放到environment中就可以了,先看下springboot的启动流程图。

可以看到业务代码第一次用到配置的地方是PropertySourcesPlaceholderConfigurer,它是一个BeanFactoryPostProcessor默认的order是最低优先级的,所以只要在执行它之前把配置放到environment对象中即可,如图标红的地方

不过很多三方的jar包可能会会自定义ApplicationContextInitializer和BeanFactoryPostProcessor。所以为了让这些jar包也用到我们的配置,所以要在更早的阶段加载配置,既然springboot提供了加载配置的扩展点,那我们直接注册一个自定义的EnvironmentPostProcessor类即可,不过因为我们加载配置的时候也要使用application.yml的配置,比如设置连接地址什么的,所以需要把我们的EnvironmentPostProcessor的优先级设置的小于ConfigDataEnvironmentPostProcessor,ConfigDataEnvironmentPostProcessor的优先级是Ordered.HIGHEST_PRECEDENCE + 10,我们只要把order设置成Ordered.HIGHEST_PRECEDENCE + 11即可

代码

ConfigCenterClient改为单例

 private static volatile ConfigCenterClient client;

    private ConfigCenterClient(String url) {
        this.url = url;
        //将配置中心的配置转换成property格式,即user.name=xxx
        List<ConfigVO> configList = getAllValidConfig();
        this.configMap = configList2ConfigMap(configList);
    }

    public static ConfigCenterClient getInstance(String url) {
        return Optional.ofNullable(client).orElseGet(() -> {
            synchronized (ConfigCenterClient.class) {
                if (client == null) {
                    client = new ConfigCenterClient(url);
                }
                return client;
            }
        });
    }

自定义EnvironmentPostProcessor

可以看到我们是从application.yml文件中获取了配置中心的地址,然后再把配置中心的配置注入到springboot中

public class ConfigEnvironmentPostProcessor implements EnvironmentPostProcessor {

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        String configCenterUrl = environment.getProperty("config.center.url");
        ConfigCenterClient configCenterClient = ConfigCenterClient.getInstance(configCenterUrl);
        Map<String, Object> configProperty = configCenterClient.getConfigProperty();

        MutablePropertySources propertySources = environment.getPropertySources();
        MapPropertySource configCenter = new MapPropertySource("configCenter", configProperty);
        propertySources.addFirst(configCenter);
    }
}

注册EnvironmentPostProcessor

org.springframework.boot.env.EnvironmentPostProcessor=\
com.config.center.config.ConfigEnvironmentPostProcessor

效果

environment对象获取配置

@Autowired
    private Environment environment;

    @Test
    public void configTest() {
        String userName = environment.getProperty("user.name");
        System.out.println(userName);
    }

xml中获取配置

public class User {
    private String userName;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	    "
       default-lazy-init="false">

    <bean id="user" class="com.config.center.test.User">
        <property name="userName" value="${user.name}"/>
    </bean>

</beans>

@Value获取配置

    @Value("${user.name}")
    private String name;

    @Test
    public void configTest() {
        System.out.println(name);
    }

@ConfigurationProperties

@Component
@ConfigurationProperties(prefix = "user")
public class UserConfig {
    private String name;
    private int age;
    private List<String> education;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List<String> getEducation() {
        return education;
    }

    public void setEducation(List<String> education) {
        this.education = education;
    }
}
    @Autowired
    private UserConfig userConfig;

    @Test
    public void configTest() {
        System.out.println(userConfig);
    }

​​​​​​​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1504161.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法与数据结构】栈的实现详解

文章目录 &#x1f4dd;栈的概念及结构&#x1f309;栈的实现 &#x1f320;栈的接口&#x1f309;初始化栈&#x1f320;入栈&#x1f309;出栈&#x1f320;获取栈顶元素&#x1f309;获取栈中有效元素个数&#x1f309;检测栈是否为空&#x1f309;销毁栈&#x1f309;Stack…

链表|142.环形链表

ListNode *detectCycle(ListNode *head) {ListNode *fast head, *slow head;while (fast && fast->next) {// 这里判断两个指针是否相等&#xff0c;所以移位操作放在前面slow slow->next;fast fast->next->next;if (slow fast) { // 相交&#xff0c…

windows11编译FFmpeg源码完整步骤

1.安装MSYS2 下载并安装MSYS2 安装GCC GCC安装成功 克隆FFmpeg源码 打开MSYS2终端并进入ffmpeg文件夹,然后输入./configure回车开始生成makefile

基于Vue的预约停车位APP设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 Vue简介 3 1.2 Node.js简介 3 1.3 JavaScript基本介绍 4 1.4 Ajax基本介绍 4 1.5 本章小结 4 2 软件需求分析与体系结构设计 5 2.1 系统定义用户 5 2.2 系统功能需求描述 5 2.3 系统用例分析 6 2. 3. 1 用户用例分析 6 2.…

ssm+springboot音乐播放器网站mybatis+jsp

测试流程 &#xff08;1&#xff09; 登录系统、填写用户名、密码选择角色&#xff0c;主要内容&#xff1a;进行权限控制。 &#xff08;2&#xff09; 用户查看音乐信息、音乐资讯功能&#xff0c;主要是测试系统实用性、方便性。 &#xff08;3&#xff09; 信息修…

CPU流水线设计

前言 大家好我是jiantaoyab&#xff0c;这是我所总结作为学习的笔记第九篇,在这里分享给大家,还有一些书籍《深入理解计算机系统》《计算机组成&#xff1a;结构化方法》《编码&#xff1a;隐匿在计算机软硬件背后的语言》&#xff0c;这篇文章讲CPU流水线设计&#xff0c;可以…

【Linux系统】线程

目录 一.线程的概念 (1)地址空间是进程的资源窗口 (2)轻量级进程 二.线程的理解 1.Linux中线程的实现方案 2. 线程VS进程 3.线程比进程更加轻量化 4.线程的优点 5.线程的缺点 6.线程共享的资源 7.线程私有的资源 三.地址空间虚拟到物理的转化 1.页框 2.重新理解文…

xss.haozi.me:0X12

</script> <script>alert(1)\</script>

同步与异步

同步 通常情况代码都是自上向下一行一行执行的 前边的代码不执行后边的代码也不会执行 同步的代码执行会出现阻塞的情况 一行代码执行慢会影响到整个程序的执行1 解决同步问题 java python通过多线程来解决 node.js通过异步方式来解决 异步 一段代码的执行不会影响到其他的…

c语言,大宗撮合交易中心系统核心模块代码

撮合交易系统&#xff08;Matching System&#xff09;常用于大宗交易&#xff0c;如股票、期货等市场&#xff0c;它负责根据买卖双方的报价和数量&#xff0c;自动撮合成交。撮合系统的核心模块通常包括订单管理、价格计算和撮合逻辑等部分。 由于撮合系统的实现复杂且依赖于…

【保姆级爬虫】微博关键词搜索并获取博文和评论内容(python+selenium+chorme)

微博爬虫记录 写这个主要是为了防止自己忘记以及之后的组内工作交接&#xff0c;至于代码美不美观&#xff0c;写的好不好&#xff0c;统统不考虑&#xff0c;我只能说&#xff0c;能跑就不错了&#xff0c;上学压根没学过python好吧&#xff0c;基本上是crtlc&ctrlv丝滑小…

nginx配置支持ipv6访问,ipv4改造ipv6

一、前言 本地测试nginx部署的web系统支持ipv6地址访问。 二、本机ipv6地址 cmd ipconfig 找到IPv6地址 其中带有%号其实是临时分配得到地址 我们可以ping一下看看 另一种ping的方式 加上中括号 还有就是去掉%号 三、nginx增加配置 server块里增加 listen [::]:80; 四、测…

php采集类snoopy2.0使用说明

我们经常采集一些网站数据时会被识别为机器人被网页被拒绝访问&#xff0c;类似这种&#xff1a; failed to open stream: HTTP request failed! HTTP/1.1 403 Forbidden网宿云安全平台检测到您当前的访问行为存在异常&#xff0c;请稍后重试... 云安全平台检测到您当前的访问…

攻防世界——elrond32

运行得到Access deny 我第一次尝试是 修改判断条件&#xff0c;jz改为jnz&#xff0c;jle改为jg&#xff0c; 这个思路运行后&#xff0c;代码因为缺少一个输入&#xff0c;而导致程序运行错误&#xff0c;所以我们只能静态分析 我们想进入Access grant 有两个函数&#xf…

一篇搞懂什么是LRU缓存|一篇搞懂LRU缓存的实现|LRUCache详解和实现

LRUCache 文章目录 LRUCache前言项目代码仓库什么时候会用到缓存(Cache)缓存满了&#xff0c;怎么办&#xff1f;什么是LRUCacheLRUCache的实现LRUCache对应的OJ题实现LRUCache对应的STL风格实现 前言 这里分享我的一些博客专栏&#xff0c;都是干货满满的。 手撕数据结构专栏…

代码理解 pseudo_labeled = outputs.max(1)[1]

import torchls torch.Tensor([[0.2,0.4],[0.3,0.2]]) print(ls.max(1))

银河麒麟服务器ky10 server wvp镜像制作

在线安装docker yum install docker -y cat >/etc/docker/daemon.json<<EOF{"registry-mirrors": ["https://registry.docker-cn.com","https://dockerhub.azk8s.cn","https://hub-mirror.c.163.com"]} EOF systemctl start …

Kubernetes 安全秘籍:5 个你必须知道的知识点

Kubernetes 安全和身份验证是确保集群和应用安全的关键。今天将深入探讨 Service Account、身份验证和RBAC的关键概念和实践&#xff0c;帮助您构建安全可靠的应用。今天本文将着重于安全相关的内容&#xff0c;并提供更详细的示例和配置说明&#xff0c;帮助兄弟们更深入地理解…

北京智源表示大模型推断少用几层也可以,节省15%算力资源

在人工智能领域&#xff0c;大语言模型&#xff08;LLMs&#xff09;已经在各种下游任务中展现出了绝佳的性能。通常采用零次学习、少次学习和微调等多种评估协议。然而&#xff0c;LLMs的推理阶段非常昂贵&#xff0c;需要大量的计算资源。理想情况下&#xff0c;LLMs的推理阶…