The configuration center writes the configuration to the spring environment

Keywords: Java Spring Back-end Middleware

preface

There are two configuration injections in the configuration center, one is before startup, and the other is dynamic configuration after configuration changes. This article mainly summarizes the pre startup configuration injection spring environment.

Pre knowledge

spring configuration will store the configuration in the PropertySource data structure. You can get the corresponding configuration through MapPropertySource, or add, delete and query the configuration
You can also

@Autowired
  private ConfigurableEnvironment environment;

Operate on configuration items at run time

Concrete practice

The implementation class inherits beanfactoryprocessor because the configuration item is modified directly before the project is started
Inheriting EnvironmentAware, you can operate spring configuration items

demo

import lombok.SneakyThrows;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.Yaml;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Iterator;

@Component
public class Test implements EnvironmentAware,BeanFactoryPostProcessor {


    @PostConstruct
    public void setup() throws FileNotFoundException {



    }

    @SneakyThrows
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }

    @SneakyThrows
    @Override
    public void setEnvironment(Environment environment) {
        Yaml yaml = new Yaml();
        Config config = yaml.loadAs(new FileInputStream(new File("D:\\project\\longPolling-demo\\src\\main\\java\\moe\\cnkirito\\demo\\xx.yaml")), Config.class);

        ((ConfigurableEnvironment) environment).getPropertySources()
                // Here is addFirst, which takes precedence over the application.properties configuration
                .addFirst(new PropertySource<String>("applicationConfig", config.getA().getB()) {
                    // a key
                    @Override
                    public Object getProperty(String s) {
                        if (s.equals("a.b")) {//
                            return source;// Return the source in the constructor: 12345
                        }
                        return null;
                    }
                });
    }
}

Yaml simulates the yml configuration of apoll, nacos and so on. After reading, it is converted to map < string, Object >, which is actually inserted into the PropertySource and then into the Environment

Key points

					// a key
                    @Override
                    public Object getProperty(String s) {
                        if (s.equals("a.b")) {//
                            return source;// Return the source in the constructor: 12345
                        }
                        return null;
                    }

For example, if I use @ Value("${a.b}") to get the value, I will judge when getProperty. If it is the same, I will return source, that is, new PropertySource("name", source);
Name is not important. After saving, a.b = 8888 will be generated. The PropertySource parameter name and then source will be generated. The types are map, key and object, so key = value will be printed

thinking

You can write the data requesting the remote configuration center in this class, then transfer the map < string, Object > to the same structure as the PropertySource, and then insert it into it.

for instance

a:
 b: ${a.b}

We can insert the value of a.b into the spring configuration, and then let it be written in at startup. Even overwrite the boot port.

Similar to nacos and apoll, these configurations are written into the spring configuration

Another idea

Background: in the absence of a registry, such as using cloud native technology, you can't get the configuration locally. At this time, you need to k8s pull the configuration.

Idea: you can write maven plug-in. When compiling (if it's a packaging environment, you have finished packing and play a hammer), pull k8s configuration, load yaml, and dump it into application.yml.

Pre knowledge: spring read configuration order

  1. Under the root directory
  2. Under config directory in root directory
  3. resources directory
  4. resources directory under config directory

Reference blog

Posted by pakenney38 on Thu, 11 Nov 2021 00:29:03 -0800