developer tip

Spring Boot-application.yml에서 맵 삽입

optionbox 2020. 9. 24. 07:45
반응형

Spring Boot-application.yml에서 맵 삽입


나는이 봄 부트 다음에 응용 프로그램 application.yml-에서 기본적으로 가지고 여기를 :

info:
   build:
      artifact: ${project.artifactId}
      name: ${project.name}
      description: ${project.description}
      version: ${project.version}

특정 값을 삽입 할 수 있습니다.

@Value("${info.build.artifact}") String value

그러나 전체 맵을 삽입하고 싶습니다. 예를 들면 다음과 같습니다.

@Value("${info}") Map<String, Object> info

그게 (또는 비슷한) 가능합니까? 분명히 yaml을 직접로드 할 수 있지만 이미 Spring에서 지원하는 것이 있는지 궁금합니다.


다음을 사용하여지도를 삽입 할 수 있습니다 @ConfigurationProperties.

import java.util.HashMap;
import java.util.Map;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
@EnableConfigurationProperties
public class MapBindingSample {

    public static void main(String[] args) throws Exception {
        System.out.println(SpringApplication.run(MapBindingSample.class, args)
                .getBean(Test.class).getInfo());
    }

    @Bean
    @ConfigurationProperties
    public Test test() {
        return new Test();
    }

    public static class Test {

        private Map<String, Object> info = new HashMap<String, Object>();

        public Map<String, Object> getInfo() {
            return this.info;
        }
    }
}

질문에서 yaml로 이것을 실행하면 다음이 생성됩니다.

{build={artifact=${project.artifactId}, version=${project.version}, name=${project.name}, description=${project.description}}}

접두사 설정, 누락 된 속성 처리 방법 제어 등에 대한 다양한 옵션이 있습니다. 자세한 내용은 javadoc 을 참조하십시오.


Below solution is a shorthand for @Andy Wilkinson's solution, except that it doesn't have to use a separate class or on a @Bean annotated method.

application.yml:

input:
  name: raja
  age: 12
  somedata:
    abcd: 1 
    bcbd: 2
    cdbd: 3

SomeComponent.java:

@Component
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "input")
class SomeComponent {

    @Value("${input.name}")
    private String name;

    @Value("${input.age}")
    private Integer age;

    private HashMap<String, Integer> somedata;

    public HashMap<String, Integer> getSomedata() {
        return somedata;
    }

    public void setSomedata(HashMap<String, Integer> somedata) {
        this.somedata = somedata;
    }

}

We can club both @Value annotation and @ConfigurationProperties, no issues. But getters and setters are important and @EnableConfigurationProperties is must to have the @ConfigurationProperties to work.

I tried this idea from groovy solution provided by @Szymon Stepniak, thought it will be useful for someone.


I run into the same problem today, but unfortunately Andy's solution didn't work for me. In Spring Boot 1.2.1.RELEASE it's even easier, but you have to be aware of a few things.

Here is the interesting part from my application.yml:

oauth:
  providers:
    google:
     api: org.scribe.builder.api.Google2Api
     key: api_key
     secret: api_secret
     callback: http://callback.your.host/oauth/google

providers map contains only one map entry, my goal is to provide dynamic configuration for other OAuth providers. I want to inject this map into a service that will initialize services based on the configuration provided in this yaml file. My initial implementation was:

@Service
@ConfigurationProperties(prefix = 'oauth')
class OAuth2ProvidersService implements InitializingBean {

    private Map<String, Map<String, String>> providers = [:]

    @Override
    void afterPropertiesSet() throws Exception {
       initialize()
    }

    private void initialize() {
       //....
    }
}

After starting the application, providers map in OAuth2ProvidersService was not initialized. I tried the solution suggested by Andy, but it didn't work as well. I use Groovy in that application, so I decided to remove private and let Groovy generates getter and setter. So my code looked like this:

@Service
@ConfigurationProperties(prefix = 'oauth')
class OAuth2ProvidersService implements InitializingBean {

    Map<String, Map<String, String>> providers = [:]

    @Override
    void afterPropertiesSet() throws Exception {
       initialize()
    }

    private void initialize() {
       //....
    }
}

After that small change everything worked.

Although there is one thing that might be worth mentioning. After I make it working I decided to make this field private and provide setter with straight argument type in the setter method. Unfortunately it wont work that. It causes org.springframework.beans.NotWritablePropertyException with message:

Invalid property 'providers[google]' of bean class [com.zinvoice.user.service.OAuth2ProvidersService]: Cannot access indexed value in property referenced in indexed property path 'providers[google]'; nested exception is org.springframework.beans.NotReadablePropertyException: Invalid property 'providers[google]' of bean class [com.zinvoice.user.service.OAuth2ProvidersService]: Bean property 'providers[google]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

Keep it in mind if you're using Groovy in your Spring Boot application.


To retrieve map from configuration you will need configuration class. @Value annotation won't do the trick, unfortunately.

Application.yml

entries:
  map:
     key1: value1
     key2: value2

Configuration class:

@Component
    @ConfigurationProperties("entries")
    @Getter
    @Setter
    public static class MyConfig {
        private Map<String, String> map;
    }

foo.bars.one.counter=1
foo.bars.one.active=false
foo.bars[two].id=IdOfBarWithKeyTwo

public class Foo {

  private Map<String, Bar> bars = new HashMap<>();

  public Map<String, Bar> getBars() { .... }
}

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding

참고URL : https://stackoverflow.com/questions/24917194/spring-boot-inject-map-from-application-yml

반응형