Three ways Spring gets its configuration

Preface

Recently, when writing frameworks, you encountered a need to load bean s based on a specific configuration (which may not exist), so you learned several ways to get the configuration in Spring.

Three ways to get configurations in Spring

  1. Get a single configuration dynamically via @Value
  2. Get configuration in bulk by @ConfigurationProperties +prefix
  3. Get a single configuration dynamically through Environment

Get a single configuration dynamically through @Value

  1. Effect

    1. Can be modified to any variable access, use more flexible
  2. Advantage

    1. Simple to use and short to use associated links
  3. shortcoming

    1. Configuration name cannot be enumerated to valid

    2. Use of each configuration needs to be redefined, which is cumbersome

    3. The project strongly depends on the definition of the configuration, and the absence of the configuration will cause the project to fail to start

  4. Use scenarios

    1. The project relies heavily on the loading of this configuration to avoid unknown problems caused by missing configuration from the source

    2. Only a few configurations are needed

  5. Code Samples

    @Configuration
    public class ConfigByValueAnnotation {
    
        @Value("${server.port}")
        private String serverPort;
    
        public String getServerPort() {
            return serverPort;
        }
    }
    
  6. Test Code

@DisplayName("multipart get config")
@SpringBootTest
public class MultipartGetConfigTest {

    private static final Logger log = LoggerFactory.getLogger(MultipartGetConfigTest.class);

    @Autowired
    private ConfigByValueAnnotation configByValueAnnotation;

    @Test
    public void getByValueAnnotation(){
        log.info("get by @Value, value: {}", configByValueAnnotation.getServerPort());
    }
}
  1. test result
org.spring.demo.MultipartGetConfigTest   : get by @Value, value: 7100

Bulk fetch via @ConfigurationProperties +prefix

  1. Effect

    1. Modifiers for configuration classes or acquisition of bulk configurations
  2. Advantage

    1. Configuration can be used simply by determining the prefix of the key, which facilitates the use of batch acquisition scenarios

    2. Since prefix matching is used, there is no need to change the code when using a new configuration with the same prefix key

  3. shortcoming

    1. Complex usage requiring the definition of configuration classes or the introduction of bean s manually

    2. Adding a new prefix with the same key may introduce instability

  4. Use scenarios

    1. Configuration requiring multiple prefixes with the same key

    2. Properrties injection expecting new configurations but not code modifications

  5. Code Samples

    @Component
    @ConfigurationProperties(prefix = "server", ignoreInvalidFields = true)
    public class ConfigByConfigurationProperties {
    
        private Integer port;
    
        public Integer getPort() {
            return port;
        }
    
        public ConfigByConfigurationProperties setPort(Integer port) {
            this.port = port;
            return this;
        }
    }
    
    @Configuration
    public class ConfigByConfigurationPropertiesV2 {
    
        @Bean("configByValueAnnotationV2")
        @ConfigurationProperties(prefix = "server2")
        public Properties properties(){
            return new Properties();
        }
    
    }
    
    1. Test Code
@DisplayName("multipart get config")
@SpringBootTest
public class MultipartGetConfigTest {

       private static final Logger log = LoggerFactory.getLogger(MultipartGetConfigTest.class);
    
       @Autowired
       private ConfigByConfigurationProperties configByConfigurationProperties;
    
       @Autowired
       @Qualifier("configByValueAnnotationV2")
       private Properties properties;
    
       @Test
       public void getByConfigurationProperties(){
           log.info("get by @ConfigurationProperties, value: {}", configByConfigurationProperties.getPort());
           log.info("get by @ConfigurationProperties and manual create bean, value: {}", properties.getProperty("port"));
       }

}
  1. test result
org.spring.demo.MultipartGetConfigTest   : get by @ConfigurationProperties, value: 7100
org.spring.demo.MultipartGetConfigTest   : get by @ConfigurationProperties and manual create bean, value: 7100

Get a single configuration dynamically through Environment

  1. Effect

    1. Used to dynamically get configurations in program code without having to define configuration key s in advance
  2. Advantage

    1. Configuration keys are acquired without pre-defined keys and are highly flexible

    2. Configuration key s can be placed and managed uniformly using enumerations

  3. shortcoming

    1. Complex usage requires inheriting the Environment interface to form a tool class for acquisition

    2. The enumeration corresponding to the get key is separated from the key definition, and the value get link is longer

  4. Use scenarios

    1. Only a small number of configurations are required

    2. Getting a configured key without a pre-defined key requires flexibility based on whether it is configured or not

  5. Code Samples

@Component
public class ConfigByEnvironment implements EnvironmentAware {

     private static final Logger log = LoggerFactory.getLogger(ConfigByEnvironment.class);
  
     private Environment environment;
  
     public Optional<String> get(String configKey){
         String config = environment.getProperty(configKey);
         return Objects.isNull(config) ? Optional.empty() : Optional.of(config);
     }
  
     public void get(String configKey, Consumer<String> consumer){
         Optional<String> config = get(configKey);
         if(!config.isPresent()){
             log.warn("application config, get config by key fail, key: {}", configKey);
         }
         config.ifPresent(consumer);
     }
  
     @Override
     public void setEnvironment(@NonNull Environment environment) {
         this.environment = environment;
     }
}

public enum ConfigByEnvironmentKey {

     SERVER_PORT("server.port", "server port");
  
     private String key;
  
     private String description;
  
     ConfigByEnvironmentKey(String key, String description) {
         this.key = key;
         this.description = description;
     }
  
     public String getKey() {
         return key;
     }
  
     public String getDescription() {
         return description;
     }
}
  1. Test Code
@DisplayName("multipart get config")
   @SpringBootTest
   public class MultipartGetConfigTest {

       private static final Logger log = LoggerFactory.getLogger(MultipartGetConfigTest.class);
    
       @Autowired
       private ConfigByEnvironment configByEnvironment;
    
       @Test
       public void getByEnvironment(){
           configByEnvironment.get(ConfigByEnvironmentKey.SERVER_PORT.getKey()).ifPresent(value -> log.info("get by environment, value: {}", value));
       }

}
  1. test result
org.spring.demo.MultipartGetConfigTest   : get by environment, value: 7100

summary

Get Configuration Advantage shortcoming Use scenarios
Get a single configuration dynamically through @Value Simple to use and short to use associated links 1. Configuration name cannot be effectively enumerated to
2. Use of each configuration needs to be redefined, which is more cumbersome
3. Projects strongly depend on the definition of a configuration, and the absence of a configuration will prevent the project from starting
1. The project relies heavily on the loading of this configuration to avoid unknown problems caused by missing configuration from the source
2. Just want to use a few configurations
Bulk fetch via @ConfigurationProperties +prefix 1. Configuration can be used simply by determining the prefix of the key, which facilitates the use of batch acquisition scenarios
2. Because prefix matching is used, there is no need to change the code when using a new configuration with the same prefix key
1. Complex usage requiring the definition of configuration classes or the introduction of bean s manually
2. Adding a new prefix with the same key may introduce instability
1. Configuration that requires multiple prefixes with the same key
2. Properrties injection expecting new configurations but not code modifications
Get a single configuration dynamically through Environment 1. Configuration key s obtained are not defined in advance and are highly flexible
2. Configuration key s can be placed and managed uniformly using enumerations
1. Complex usage requires inheriting the Environment interface to form a tool class for acquisition
2. The enumeration corresponding to the get key is separated from the key definition, and the value get link is longer
1. Use only a small amount of configuration
2. Getting the configured key is not defined in advance and needs to be used flexibly depending on whether the configuration is available or not.

This code sample has been placed in githubTest Code Location And take what you need.
This article was first published in cartoon's blog

Added by Darrel on Mon, 07 Mar 2022 20:26:17 +0200