配置动态刷新 - 实现

结构说明


结构.PNG

MyEnvironmentPostProcessor

  • 启动可观察效果

  • 注意:修改时要单独打开target/classes/myEnvironment.properties修改配置,不要使用idea打开修改

1.MyEnvironmentPostProcessor
package com.zsl.springbootlearn.json.environmentPostProcessor;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import java.io.IOException;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

/**
 *  环境配置参数动态更新 -新建线程调度执行
 *
 * * */
public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor{
    private String path;
    private final String DEFAULT_LOCATION=ResourceLoader.CLASSPATH_URL_PREFIX;
    private final String DEFAULT_NAME="myEnvironment";
    private ResourceLoader resourceLoader=new DefaultResourceLoader();

    private Properties properties = new Properties();

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {

        String location=environment.getProperty("myenvironment.location")!=null? environment.getProperty("myenvironment.location"):DEFAULT_LOCATION;
        String name=environment.getProperty("myenvironment.name")!=null? environment.getProperty("myenvironment.name"):DEFAULT_NAME;
        path=location+name+".properties";
        System.out.println(path);
        properties=loadProperties(path);

        //环境名称随意取,但尽量不能和其他环境名称相同,避免不生效
        PropertiesPropertySource propertySource = new PropertiesPropertySource("myEnvironmentPostProcessor", properties);
        environment.getPropertySources().addLast(propertySource);

        //TODO 新建线程并将properties传给该线程轮询处理该properties
        Thread thread=new Thread(new Runnable(){
            @Override
            public void run() {
                while(true){
                    System.out.println("MyEnvironmentPostProcessorThread线程");
                    Properties propertiesTemp=loadProperties(path);
                    System.out.println("    propertiesTemp"+propertiesTemp);
                    System.out.println("    properties"+properties);
                    System.out.println("    配置是否被修改:"+!properties.equals(propertiesTemp));
                    if(properties!=null && !properties.equals(propertiesTemp)){
                        Set keys=propertiesTemp.stringPropertyNames();
                        Iterator iterator=keys.iterator();
                        while(iterator.hasNext()){
                            String key=iterator.next();
                            properties.setProperty(key,propertiesTemp.getProperty(key));
                        }
                    }
                    try {
                        Thread.sleep(2000); //每2s一次
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        });
        thread.start();

    }

    /**
     * 从指定的全路径加载配置
     * */
    private Properties loadProperties(String location){
        Properties properties = new Properties();
        Resource resource =resourceLoader.getResource(location);
        try {
            properties.load(resource.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties;
    }

}

测试

  • @Scope("prototype") 很重要
2.Test
@Component
@Scope("prototype")
public class Test {
    @Value("${test.name}")
    private String name;

    public String getName() {
        return name;
    }

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

3.Main
package com.zsl.springbootlearn.json;

import com.zsl.springbootlearn.json.environmentPostProcessor.Test;
import com.zsl.springbootlearn.json.registry.CircuitUtil;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.ApplicationContext;

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class JsonStarter {
    public static void main(String[] args) {
        ApplicationContext applicationContext=SpringApplication.run(JsonStarter.class,args);
        applicationContext.getBean(CircuitUtil.class).call();
        while(true){
            System.out.println("Main 线程");
            System.out.println("    Test.name="+applicationContext.getBean(Test.class).getName());
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

结果:

执行过程中修改配置文件后结果:


结果.PNG

改进

可以使用文件监听器进行修改,在文件发生改变时才修改
类似服务端推技术

你可能感兴趣的:(配置动态刷新 - 实现)