source

Spring AppContext 없이 @ConfigurationProperties를 수동으로 로드할 수 있습니까?

nicesource 2023. 7. 3. 22:56
반응형

Spring AppContext 없이 @ConfigurationProperties를 수동으로 로드할 수 있습니까?

다음으로 표시된 클래스를 로드할 수 있는 방법이 있습니까?@ConfigurationPropertiesSpring Context를 직접 사용하지 않고도?기본적으로 저는 스프링 라이프사이클 외부에서 수동으로 인스턴스화하는 것을 제외하고 스프링이 수행하는 모든 스마트 로직을 재사용하고 싶습니다.

저는 봄(부트)에 행복하게 적재되는 콩을 가지고 있으며 이것을 다른 서비스 콩에 주입할 수 있습니다.

@ConfigurationProperties(prefix="my")
public class MySettings {
    String property1;
    File property2;
} 

자세한 내용은 스프링 문서를 참조하십시오. http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/ #boot-syslog-external-config-command-line-args

그러나 이제 Spring(Hibernate) 외부에서 만든 클래스에서 이 빈에 액세스해야 합니다.이 클래스는 앱 시작 프로세스 초기에 생성되므로 Spring Boot는 아직 기존의 Lookup Helper 메서드나 롤 마이셀프 정적 참조를 통해 애플리케이션 컨텍스트를 사용할 수 없습니다.

대신 다음과 같은 작업을 수행하고자 합니다.

MySettings mySettings = new MySettings(); 
SpringPropertyLoadingMagicClass loader = new SpringPropertyLoadingMagicClass();
loader.populatePropertyValues(mySettings);

그리고 명령행, 시스템 속성, app.properties 등에서 MySettings의 모든 값이 로드되도록 합니다.봄에 이런 것을 하는 수업이 있습니까, 아니면 그것이 모두 지원 맥락과 너무 뒤섞여 있습니까?

분명히 속성 파일을 직접 로드할 수 있지만, 스프링 부트의 논리는 명령줄 변수(예: --my.sv1=xxx), 시스템 변수, application.properties 또는 심지어 yaml 파일을 사용하여 유지하고 싶습니다.property2는 File)이므로 Spring 컨텍스트에서 사용할 때와 정확히 동일하게 작동합니다.

가능한 꿈인가요, 아니면 꿈인가요?

도와주셔서 감사합니다!

저도 같은 "문제"가 있었습니다.SpringBoot 버전 1.3.xxx 및 1.4.1에서 해결한 방법은 다음과 같습니다.

다음과 같은 yaml 구성 파일이 있다고 가정합니다.

foo:
  apis:
      -
       name: Happy Api
       path: /happyApi.json?v=bar
      -
       name: Grumpy Api
       path: /grumpyApi.json?v=grrr

그리고 우리는 다음을 가지고 있습니다.ConfigurationProperties:

@ConfigurationProperties(prefix = "foo")
public class ApisProperties {
    private List<ApiPath> apis = Lists.newArrayList();

    public ApisProperties() {
    }

    public List<ApiPath> getApis() {
        return apis;
    }

    public static class ApiPath {
        private String name;
        private String path;

        public String getName() {
            return name;
        }

        public void setName(final String aName) {
            name = aName;
        }

        public String getPath() {
            return path;
        }

        public void setPath(final String aPath) {
            path = aPath;
        }
    }
} 

그런 다음 Spring Boot의 "매직" 작업을 프로그래밍 방식으로 수행하려면(예: 정적 방법으로 일부 속성 로드) 다음을 수행할 수 있습니다.

private static ApisProperties apiProperties() {
    try {
        ClassPathResource resource;
        resource = new ClassPathResource("/config/application.yml");

        YamlPropertiesFactoryBean factoryBean;
        factoryBean = new YamlPropertiesFactoryBean();
        factoryBean.setSingleton(true); // optional depends on your use-case
        factoryBean.setResources(resource);

        Properties properties;
        properties = factoryBean.getObject();

        MutablePropertySources propertySources;
        propertySources = new MutablePropertySources();
        propertySources.addLast(new PropertiesPropertySource("apis", properties));

        ApisProperties apisProperties;
        apisProperties = new ApisProperties();

        PropertiesConfigurationFactory<ApisProperties> configurationFactory;
        configurationFactory = new PropertiesConfigurationFactory<>(apisProperties);
        configurationFactory.setPropertySources(propertySources);
        configurationFactory.setTargetName("foo"); // it's the same prefix as the one defined in the @ConfigurationProperties

        configurationFactory.bindPropertiesToTarget();
        return apisProperties; // apiProperties are fed with the values defined in the application.yaml

    } catch (BindException e) {
        throw new IllegalArgumentException(e);

    }
}

스프링 부트 2.x에 대한 ctranxuan의 답변에 대한 업데이트입니다.우리의 상황에서, 우리는 유닛 테스트를 위해 Spring 컨텍스트를 회전시키는 것을 피하지만, 우리의 구성 클래스를 테스트하는 것을 좋아합니다.AppConfig이 예에서, 그리고 그 설정은 다음과 같이 접두사가 붙습니다.app):

public class AppConfigTest {
  private static AppConfig config;

  @BeforeClass
  public static void init() {
    YamlPropertiesFactoryBean factoryBean = new YamlPropertiesFactoryBean();
    factoryBean.setResources(new ClassPathResource("application.yaml"));

    Properties properties = factoryBean.getObject();

    ConfigurationPropertySource propertySource = new MapConfigurationPropertySource(properties);
    Binder binder = new Binder(propertySource);

    config = binder.bind("app", AppConfig.class).get(); // same prefix as @ConfigurationProperties
  }
}

있는 는 "마법"입니다.PropertiesConfigurationFactory하지만 한 번만 바인딩하면 된다면 Spring이 대신 바인딩할 수 있을 것이고, 라이프사이클 문제가 있는 경우에는 이러한 문제를 해결하는 것이 좋습니다(다른 문제가 발생할 경우).

이 게시물은 비슷한 방향으로 진행되지만 유효성 확인 및 속성 자리 표시자 해결을 통해 마지막 답변을 확장합니다.

@Value 주석에 대한 Spring Boot Binder API 지원

@ValueConfigurationProperty 것 된 값이 "s"의 가 아닌 ).ConfigurationProperty접두사 네임스페이스).

import org.springframework.boot.context.properties.bind.Binder
val binder = Binder.get(environment)
binder.bind(prefix, MySettings.class).get

언급URL : https://stackoverflow.com/questions/26940583/can-i-manually-load-configurationproperties-without-the-spring-appcontext

반응형