복붙노트

[SPRING] SpringBoot 프로젝트에서 PropertySourcesPlaceholderConfigurer가 환경에 등록되지 않았습니다.

SPRING

SpringBoot 프로젝트에서 PropertySourcesPlaceholderConfigurer가 환경에 등록되지 않았습니다.

나는 스프링 부트 명령 줄 인수를 사용하여 파일에서 속성을 읽는 작업 프로젝트를 옮길 것이다. 다음은 @Configuration 클래스의 관련된 부분입니다.

@Configuration
class RemoteCommunication {

    @Inject
    StandardServletEnvironment env


    @Bean
    static PropertySourcesPlaceholderConfigurer placeholderConfigurer () {
        // VERIFIED this is executing...
        PropertySourcesPlaceholderConfigurer target = new PropertySourcesPlaceholderConfigurer()
        // VERIFIED this files exists, is readable, is a valid properties file
        target.setLocation (new FileSystemResource ('/Users/me/Desktop/mess.properties'))
        // A Debugger does NOT show this property source in the inject Environment
        target
    }


    @Bean  // There are many of these for different services, only one shown here.
    MedicalSorIdService medicalSorIdService () {
        serviceInstantiator (MedicalSorIdService_EpicSoap, 'uri.sor.id.lookup.internal')
    }


    // HELPER METHODS...


    private <T> T serviceInstantiator (final Class<T> classToInstantiate, final String propertyKeyPrimary) {
        def value = retrieveSpringPropertyFromConfigurationParameter (propertyKeyPrimary)
        classToInstantiate.newInstance (value)
    }


    private def retrieveSpringPropertyFromConfigurationParameter (String propertyKeyPrimary) {
        // PROBLEM: the property is not found in the Environment
        def value = env.getProperty (propertyKeyPrimary, '')
        if (value.isEmpty ()) throw new IllegalStateException ('Missing configuration parameter: ' + "\"$propertyKeyPrimary\"")
        value
    }

속성을 주입하기 위해 @Value를 사용하면 효과가 있지만 가능하다면 환경과 직접 작업하는 편이 낫습니다. 설정이 환경에 없다면 @Value가 어디에서 가져 오는지 정확히 알 수 없습니다 ...

env.getProperty ()는 속성을 지정하는 명령 줄 인수를 전달할 때 계속 잘 작동합니다.

어떤 제안이라도 환영합니다!

해결법

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

    1.여기서 문제는 단순화를 위해 PropertySourcesPlaceholderConfigurer와 StandardServletEnvironment 또는 환경을 구분하는 것입니다.

    여기서 문제는 단순화를 위해 PropertySourcesPlaceholderConfigurer와 StandardServletEnvironment 또는 환경을 구분하는 것입니다.

    환경은 전체 ApplicationContext를 뒷받침하고 많은 속성을 해결할 수있는 객체입니다 (Environment 인터페이스는 PropertyResolver를 확장 함). ConfigurableEnvironment에는 getPropertySources ()를 통해 검색 할 수있는 MutablePropertySources 객체가 있습니다. 이 MutablePropertySources는 요청 된 속성을 해결하기 위해 검사되는 PropertySource 객체의 LinkedList를 보유합니다.

    PropertySourcesPlaceholderConfigurer는 자체 상태를 가진 별도의 객체입니다. 속성 자리 표시자를 해결하기 위해 자체 MutablePropertySources 객체를 보유합니다. PropertySourcesPlaceholderConfigurer는 EnvironmentAware를 구현하므로 ApplicationContext가이를 획득하면 Environment 객체를 제공합니다. PropertySourcesPlaceholderConfigurer는이 Environment의 MutablePropertySources를 추가합니다. 그런 다음 setLocation ()으로 지정한 다양한 Resource 객체를 추가 속성으로 추가합니다. 이러한 Resource 객체는 Environment의 MutablePropertySources에 추가되지 않기 때문에 env.getProperty (String)에서는 사용할 수 없습니다.

    따라서 PropertySourcesPlaceholderConfigurer가 환경에 직접로드 한 속성을 환경으로 가져올 수 없습니다. 대신에 환경의 MutablePropertySouces에 직접 추가 할 수 있습니다. 한 가지 방법은

    @PostConstruct
    public void setup() throws IOException {
        Resource resource = new FileSystemResource("spring.properties"); // your file
        Properties result = new Properties();
        PropertiesLoaderUtils.fillProperties(result, resource);
        env.getPropertySources().addLast(new PropertiesPropertySource("custom", result));
    }
    

    또는 단순히 (thanks @ M.Deinum)

    @PostConstruct
    public void setup() throws IOException {
        env.getPropertySources().addLast(new ResourcePropertySource("custom", "file:spring.properties")); // the name 'custom' can come from anywhere
    }
    

    @PropertySource를 추가하는 것과 같은 효과가 있습니다. 환경에 직접 추가되지만 동적으로 수행하는 것이 아니라 정적으로 수행하는 것입니다.

  2. ==============================

    2.SpringBoot에서는 @EnableConfigurationProperties 주석을 사용하는 것으로 충분합니다. PropertySourcesPlaceholderConfigurer를 설정할 필요가 없습니다.

    SpringBoot에서는 @EnableConfigurationProperties 주석을 사용하는 것으로 충분합니다. PropertySourcesPlaceholderConfigurer를 설정할 필요가 없습니다.

    그런 다음 POJO에서 @ConfigurationProperties 주석을 추가하면 Spring은 application.properties에 정의 된 속성을 자동으로 주입한다.

    YAML 파일을 사용할 수도 있습니다 - 클래스 패스에 적절한 종속성 (예 : SnakeYaml)을 추가하기 만하면됩니다

    자세한 예제는 http://spring.io/blog/2013/10/30/empowering-your-apps-with-spring-boot-s-property-support에서 확인할 수 있습니다.

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

    3.아마도 -Dspring.config.location = ... (또는 SPRING_CONFIG_LOCATION을 env var로 설정)하면됩니까? 이것은 런타임에 app.properties보다 우선시되는 app의 기본 경로에 추가 설정 파일을 추가하는 효과가 있습니까? 자세한 내용은 howto docs를 참조하십시오.

    아마도 -Dspring.config.location = ... (또는 SPRING_CONFIG_LOCATION을 env var로 설정)하면됩니까? 이것은 런타임에 app.properties보다 우선시되는 app의 기본 경로에 추가 설정 파일을 추가하는 효과가 있습니까? 자세한 내용은 howto docs를 참조하십시오.

  4. ==============================

    4.PropertySourcesPlaceholderConfigurer 인스턴스를 생성하는 동안이 작업을 수행했습니다.

    PropertySourcesPlaceholderConfigurer 인스턴스를 생성하는 동안이 작업을 수행했습니다.

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurerBean(Environment env) {
        PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
        YamlPropertiesFactoryBean yamlFactorybean = new YamlPropertiesFactoryBean();
        yamlFactorybean.setResources(determineResources(env));
    
        PropertiesPropertySource yampProperties = new PropertiesPropertySource("yml", yamlFactorybean.getObject());
    
        ((AbstractEnvironment)env).getPropertySources().addLast(yampProperties);
    
        propertySourcesPlaceholderConfigurer.setProperties(yamlFactorybean.getObject());
    
        return propertySourcesPlaceholderConfigurer;
    }
    
    
    private static Resource[] determineResources(Environment env){
        int numberOfActiveProfiles = env.getActiveProfiles().length;
        ArrayList<Resource> properties =  new ArrayList(numberOfActiveProfiles);
        properties.add( new ClassPathResource("application.yml") );
    
        for (String profile : env.getActiveProfiles()){
            String yamlFile = "application-"+profile+".yml";
            ClassPathResource props = new ClassPathResource(yamlFile);
    
            if (!props.exists()){
                log.info("Configuration file {} for profile {} does not exist");
                continue;
            }
    
            properties.add(props);
        }
    
        if (log.isDebugEnabled())
            log.debug("Populating application context with properties files: {}", properties);
    
        return properties.toArray(new Resource[properties.size()]);
    }
    
  5. from https://stackoverflow.com/questions/21100729/propertysourcesplaceholderconfigurer-not-registering-with-environment-in-a-sprin by cc-by-sa and MIT license