복붙노트

[SPRING] Typesafe Config로 지원되는 Spring 환경

SPRING

Typesafe Config로 지원되는 Spring 환경

내 프로젝트에서 typesafe config (HOCON 설정 파일)을 사용하여 쉽고 체계적인 응용 프로그램 구성을 용이하게하고 싶습니다. 현재 일반적인 Java 속성 파일 (application.properties)을 사용하고 있으며 큰 프로젝트에서 처리하기가 어렵습니다.

내 프로젝트는 봄 MVC (봄 부팅 프로젝트 아님)입니다. typesafe 설정에 의해 뒷받침되는 (내 서비스에 주입되는) Spring 환경을 되돌릴 수있는 방법이 있습니까? @Value 주석, @Autowired 환경 등등 같이 나의 기존 환경 사용법을 제동하면 안된다.

최소한의 노력과 코드 변경만으로 어떻게해야합니까?

이것이 나의 현재 해결책이다 : 찾고있는 다른 방법이 더있다.

@Configuration
public class PropertyLoader{
    private static Logger logger = LoggerFactory.getLogger(PropertyLoader.class);

    @Bean
    @Autowired
    public static PropertySourcesPlaceholderConfigurer properties(Environment env) {
        PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();

        Config conf = ConfigFactory.load();
        conf.resolve();
        TypesafePropertySource propertySource = new TypesafePropertySource("hoconSource", conf);

        ConfigurableEnvironment environment = (StandardEnvironment)env;
        MutablePropertySources propertySources = environment.getPropertySources();
        propertySources.addLast(propertySource);
        pspc.setPropertySources(propertySources);

        return pspc;
    }
}

class TypesafePropertySource extends PropertySource<Config>{
    public TypesafePropertySource(String name, Config source) {
        super(name, source);
    }

    @Override
    public Object getProperty(String name) {
        return this.getSource().getAnyRef(name);
    }
}

해결법

  1. ==============================

    1.PropertySource를 속성 소스에 수동으로 추가하는 것보다 약간 더 관용적 인 방법을 찾았다 고 생각합니다. PropertySourceFactory 만들기 및 @PropertySource를 사용하여 참조

    PropertySource를 속성 소스에 수동으로 추가하는 것보다 약간 더 관용적 인 방법을 찾았다 고 생각합니다. PropertySourceFactory 만들기 및 @PropertySource를 사용하여 참조

    첫째, 타입 팩 ConfigSource는 가지고있는 것과 거의 같습니다 :

    public class TypesafeConfigPropertySource extends PropertySource<Config> {
        public TypesafeConfigPropertySource(String name, Config source) {
            super(name, source);
        }
    
        @Override
        public Object getProperty(String path) {
            if (source.hasPath(path)) {
                return source.getAnyRef(path);
            }
            return null;
        }
    }
    

    다음으로, 우리는 그 속성 소스를 반환하는 PropertySource 팩토리를 생성한다.

    public class TypesafePropertySourceFactory implements PropertySourceFactory {
    
        @Override
        public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
            Config config = ConfigFactory.load(resource.getResource().getFilename()).resolve();
    
            String safeName = name == null ? "typeSafe" : name;
            return new TypesafeConfigPropertySource(safeName, config);
        }
    
    }
    

    마지막으로, 설정 파일에서 PropertySource를 직접 추가하지 않고 다른 PropertySource처럼 속성 소스를 참조 할 수 있습니다.

    @Configuration
    @PropertySource(factory=TypesafePropertySourceFactory.class, value="someconfig.conf")
    public class PropertyLoader {
        // Nothing needed here
    }
    
  2. ==============================

    2.다음과 같이 PropertySource 클래스를 작성합니다. 값과 null을 반환해야하는 차이가있는 것과 비슷하며 누락 된 예외를 던지지 않게합니다.

    다음과 같이 PropertySource 클래스를 작성합니다. 값과 null을 반환해야하는 차이가있는 것과 비슷하며 누락 된 예외를 던지지 않게합니다.

    public class TypesafeConfigPropertySource extends PropertySource<Config> {
    
        private static final Logger LOG = getLogger(TypesafeConfigPropertySource.class);
    
        public TypesafeConfigPropertySource(String name, Config source) {
            super(name, source);
        }
    
        @Override
        public Object getProperty(String name) {
            try {
                return source.getAnyRef(name);
            } catch (ConfigException.Missing missing) {
                LOG.trace("Property requested [{}] is not set", name);
                return null;
            }
        }
    }
    

    두 번째 단계는 다음과 같이 bean을 정의하는 것입니다.

        @Bean
        public TypesafeConfigPropertySource provideTypesafeConfigPropertySource(
            ConfigurableEnvironment env) {
    
            Config conf = ConfigFactory.load().resolve();
            TypesafeConfigPropertySource source = 
                              new TypesafeConfigPropertySource("typeSafe", conf);
            MutablePropertySources sources = env.getPropertySources();
            sources.addFirst(source); // Choose if you want it first or last
            return source;
    
        }
    

    다른 bean에 프라퍼티를 autowire하고 싶다면, annotation @DependsOn이 먼저로드되었는지 확인하기 위해 propertysource 빈에 추가합니다.

    희망이 도움이된다.

  3. ==============================

    3.Laplie Anderson은 몇 가지 작은 개선 사항에 대한 답변을 제공합니다.

    Laplie Anderson은 몇 가지 작은 개선 사항에 대한 답변을 제공합니다.

    TypesafePropertySourceFactory.java

    import java.io.IOException;
    
    import org.springframework.core.env.PropertySource;
    import org.springframework.core.io.support.EncodedResource;
    import org.springframework.core.io.support.PropertySourceFactory;
    
    import com.typesafe.config.Config;
    import com.typesafe.config.ConfigFactory;
    import com.typesafe.config.ConfigParseOptions;
    import com.typesafe.config.ConfigResolveOptions;
    
    public class TypesafePropertySourceFactory implements PropertySourceFactory {
    
      @Override
      public PropertySource<?> createPropertySource(String name, EncodedResource resource)
          throws IOException {
        Config config = ConfigFactory
            .load(resource.getResource().getFilename(),
                ConfigParseOptions.defaults().setAllowMissing(false),
                ConfigResolveOptions.noSystem()).resolve();
    
        String safeName = name == null ? "typeSafe" : name;
        return new TypesafeConfigPropertySource(safeName, config);
      }
    }
    

    TypesafeConfigPropertySource.java

    import org.springframework.core.env.PropertySource;
    
    import com.typesafe.config.Config;
    
    public class TypesafeConfigPropertySource extends PropertySource<Config> {
      public TypesafeConfigPropertySource(String name, Config source) {
        super(name, source);
      }
    
      @Override
      public Object getProperty(String path) {
        if (path.contains("["))
          return null;
        if (path.contains(":"))
          return null;
        if (source.hasPath(path)) {
          return source.getAnyRef(path);
        }
        return null;
      }
    }
    
  4. from https://stackoverflow.com/questions/38803381/spring-environment-backed-by-typesafe-config by cc-by-sa and MIT license