SpringBoot基礎篇配置信息之配置刷新

更多Spring文章,歡迎點擊 一灰灰Blog-Spring專題java

配置的刷新,從第一篇就提出了這個問題,可是一直都沒有說到,那麼配置加載完畢以後可否在主動刷新呢?git

若是對SpringCloud有了解的話,會直到有個配置中心的微服務,專門就是來作配置遠程拉取,固然也支持刷新了,這是否意味着能夠支持刷新呢,若是支持該怎麼作?github

<!-- more -->web

I. 配置動態刷新

本篇將介紹並演示如何實現配置信息的刷新,但不會涉及到底層的實現原理,想要探究裏面的神奇,能夠網上google一下,或者期待後續的源碼分析篇spring

1. ContextReferer

咱們這裏主要藉助這個類來實現配置刷新,至於從哪裏撈出來的這個東西,從Spring-Cloud-Config出發,看了下它怎麼玩的,而後依葫蘆畫瓢app

這個類全路徑爲 org.springframework.cloud.context.refresh.ContextRefresher,所以你的SpringBoot項目須要作一點修改dom

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-context</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

接下來就簡單了,直接調用這個類的refresh()方法就能夠了,just so easy~spring-boot

2. 代碼演示

配置文件: application.yml微服務

biz:
  refresh: ${random.long}
  key: refresh-test

rest:
  uuid: ${random.uuid}

server:
  port: 8081

讀取配置的bean,演示了兩種獲取方式,分別以下源碼分析

@Data
@Component
@ConfigurationProperties(prefix = "biz")
public class BizConfig {
    private String key;
    private Long refresh;
}

開啓刷新的@Value註解方式,注意下面的@RefreshScoe註解,這個必須有,負責更新後的配置不會同步

@Data
@RefreshScope
@Component
public class ValueConfig {
    @Value("${rest.uuid}")
    private String uuid;
}

測試Controller以下

@RestController
public class DemoController {
    @Autowired
    private ContextRefresher contextRefresher;

    @Autowired
    private BizConfig bizConfig;

    @Autowired
    private ValueConfig valueConfig;

    @GetMapping(path = "/show")
    public String show() {
        JSONObject res = new JSONObject();
        res.put("biz", JSONObject.toJSONString(bizConfig));
        res.put("uuid", valueConfig.getUuid());
        return res.toJSONString();
    }

    @GetMapping(path = "/refresh")
    public String refresh() {
        new Thread(() -> contextRefresher.refresh()).start();
        return show();
    }
}

3. 實例演示

啓動上面的應用,而後開啓愉快的測試,調用refresh接口,發現每次的返回都不同(由於配置文件使用了random隨機生成),可是訪問show接口時,每次返回的都是同樣的,也就是說refresh接口中確實實現了配置的刷新

實例演示

說明

  • 使用ConfigurationProperties方式獲取註解時,自動支持刷新配置
  • 使用@Value註解的方式,須要開啓@RefreshScope註解(上面沒有演示不開啓這個註解的狀況, 建議有興趣的能夠本身嘗試一下)

II. 配置變動監聽

既然配置能刷新,那麼若是我但願獲取配置變動的事件,而後作一些其餘的事情,是否ok呢?

其實進入 ContextRefresher 的源碼,看下refresh接口,就很明確了

public synchronized Set<String> refresh() {
	Map<String, Object> before = extract(
			this.context.getEnvironment().getPropertySources());
	addConfigFilesToEnvironment();
	Set<String> keys = changes(before,
			extract(this.context.getEnvironment().getPropertySources())).keySet();
	// 注意這一行,拋出了一個變動事件
	this.context.publishEvent(new EnvironmentChangeEvent(context, keys));
	this.scope.refreshAll();
	return keys;
}

1. 配置變動監聽

從上面的源碼中,藉助spring的事件通知機制,很簡單就能夠知道該怎麼作了,來一個簡單的demo,這裏順帶測試下上面漏掉的不刷新的場景

@RestController
public class DemoController {

    @Autowired
    private ContextRefresher contextRefresher;

    @Autowired
    private BizConfig bizConfig;

    @Autowired
    private ValueConfig valueConfig;

    @Value("${rest.uuid}")
    private String uuid;

    @GetMapping(path = "/show")
    public String show() {
        JSONObject res = new JSONObject();
        res.put("biz", JSONObject.toJSONString(bizConfig));
        res.put("uuid", valueConfig.getUuid());
        res.put("no-refresh", uuid);
        return res.toJSONString();
    }

    @GetMapping(path = "/refresh")
    public String refresh() {
        new Thread(() -> contextRefresher.refresh()).start();
        return show();
    }

    @EventListener
    public void envListener(EnvironmentChangeEvent event) {
        System.out.println("conf change: " + event);
    }
}

直接將Listener寫在Controller類內部... 原則上不推薦上面的寫法

2. 實測

依然來個實測,主要注意下控制檯的輸出便可

配置刷新事件監聽

III. 其餘

0. 項目

1. 一灰灰Blog

一灰灰的我的博客,記錄全部學習和工做中的博文,歡迎你們前去逛逛

2. 聲明

盡信書則不如,已上內容,純屬一家之言,因我的能力有限,不免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激

3. 掃描關注

一灰灰blog

QrCode

知識星球

goals

相關文章
相關標籤/搜索