javaspringconfigurationspring-annotations

Spring Annotations Import Config not called


I am trying to make an application that uses Spring annotations to import the configurations. For this question i narrowed it down to two files. The Startup class:

package core;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Slf4j
@Configuration
@Import(ConfigSettings.class)
public class Startup {
    public static void main (String args[]) {
    log.info("main class");
    }
}

and the ConfigSettings package core;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Slf4j
@Configuration
@ComponentScan({"connections", "filter"})
@PropertySource({"classpath:config/${env.config:dev}.application.properties"})
public class ConfigSettings {

    public ConfigSettings() {
    log.info("Constructor ConfigSettings");
    }
}

I expected the outcome to be:

[INFO]Constructor ConfigSettings
[INFO]main class

But it only shows mainclass. It looks like the constructor of the config settings is not called at all. I expect it to call it because of the import annotation.

Can anyone explain what is going wrong? Thank you in advance!


Solution

  • Your best bet is to make the config class return config object that contains your values. Generally I don't tend to add an all-encompassing config object, but have a config file for each component (database, controllers, etc...).

    You can then return the configured object as a bean and let spring inject it. If I were to make a config file for a RestTemplate (as a simple example):

    @Service
    public class RestClientConfig {
    
        @Value("${your.config.value}")
        private String yourValue;
    
    
        private final RestTemplate restTemplate = new RestTemplate();
    
        @Bean
        public RestTemplate restTemplate() {
          // Configure it, using your imported values
          // ...
    
          return restTemplate;
       }
    }
    

    However, the main method is outside of the spring container and you won't be able to bootstrap it that way, but with the above method you can call the configured component directly where you need to use it.