How to use YamlPropertiesFactoryBean to load YAML files using Spring Framework 4.1?

。_饼干妹妹 提交于 2019-11-26 04:48:08

问题


I have a spring application that is currently using *.properties files and I want to have it using YAML files instead.

I found the class YamlPropertiesFactoryBean that seems to be capable of doing what I need.

My problem is that I\'m not sure how to use this class in my Spring application (which is using annotation based configuration). It seems I should configure it in the PropertySourcesPlaceholderConfigurer with the setBeanFactory method.

Previously I was loading property files using @PropertySource as follows:

@Configuration
@PropertySource(\"classpath:/default.properties\")
public class PropertiesConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

How can I enable the YamlPropertiesFactoryBean in the PropertySourcesPlaceholderConfigurer so that I can load YAML files directly? Or is there another way of doing this?

Thanks.

My application is using annotation based config and I\'m using Spring Framework 4.1.4. I found some information but it always pointed me to Spring Boot, like this one.


回答1:


With XML config I've been using this construct:

<context:annotation-config/>

<bean id="yamlProperties" class="org.springframework.beans.factory.config.YamlPropertiesFactoryBean">
    <property name="resources" value="classpath:test.yml"/>
</bean>

<context:property-placeholder properties-ref="yamlProperties"/>

Of course you have to have the snakeyaml dependency on your runtime classpath.

I prefer XML config over the java config, but I recon it shouldn't be hard to convert it.

edit:
java config for completeness sake

@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
  PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
  YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
  yaml.setResources(new ClassPathResource("default.yml"));
  propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
  return propertySourcesPlaceholderConfigurer;
}



回答2:


To read .yml file in Spring you can use next approach.

For example you have this .yml file:

section1:
  key1: "value1"
  key2: "value2"
section2:
  key1: "value1"
  key2: "value2"

Then define 2 Java POJOs:

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "section1")
public class MyCustomSection1 {
    private String key1;
    private String key2;

    // define setters and getters.
}

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "section2")
public class MyCustomSection1 {
    private String key1;
    private String key2;

    // define setters and getters.
}

Now you can autowire these beans in your component. For example:

@Component
public class MyPropertiesAggregator {

    @Autowired
    private MyCustomSection1 section;
}

In case you are using Spring Boot everything will be auto scaned and instantiated:

@SpringBootApplication
public class MainBootApplication {
     public static void main(String[] args) {
        new SpringApplicationBuilder()
            .sources(MainBootApplication.class)
            .bannerMode(OFF)
            .run(args);
     }
}

If you'are using JUnit there is a basic test setup for loading YAML file:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(MainBootApplication.class)
public class MyJUnitTests {
    ...
}

If you're using TestNG there is a sample of test configuration:

@SpringApplicationConfiguration(MainBootApplication.class)
public abstract class BaseITTest extends AbstractTestNGSpringContextTests {
    ....
}



回答3:


`

package com.yaml.yamlsample;

import com.yaml.yamlsample.config.factory.YamlPropertySourceFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;

@SpringBootApplication
@PropertySource(value = "classpath:My-Yaml-Example-File.yml", factory = YamlPropertySourceFactory.class)
public class YamlSampleApplication implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(YamlSampleApplication.class, args);
    }

    @Value("${person.firstName}")
    private String firstName;
    @Override
    public void run(String... args) throws Exception {
        System.out.println("first Name              :" + firstName);
    }
}


package com.yaml.yamlsample.config.factory;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
import java.io.IOException;
import java.util.List;

public class YamlPropertySourceFactory extends DefaultPropertySourceFactory {
    @Override
    public PropertySource createPropertySource(String name, EncodedResource resource) throws IOException {
         if (resource == null) {
            return super.createPropertySource(name, resource);
        }
        List<PropertySource<?>> propertySourceList = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource());
        if (!propertySourceList.isEmpty()) {
            return propertySourceList.iterator().next();
        }
        return super.createPropertySource(name, resource);
    }
}

My-Yaml-Example-File.yml

person:
  firstName: Mahmoud
  middleName:Ahmed

Reference my example on github spring-boot-yaml-sample So you can load yaml files and inject values using @Value()




回答4:


I spend 5 to 6 hours in understanding why external configuration of yml/yaml file(not application.yml) are so different.I read various articles, stack overflow questions but didn't get correct answer.

I was stuck in between like I was able to use custom yml file value using YamlPropertySourceLoader but not able to use @Value because it is giving me error like Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'fullname.firstname' in value "${fullname.firstname}"

fullname is a property in yml.

Then I used "turtlesallthewaydown" given above solution, then at last I was able to use @Value without any issues for yaml files and I removed YamlPropertySourceLoader.

Now I understand the difference between YamlPropertySourceLoader and PropertySourcesPlaceholderConfigurer, a big thanks, however I have added these changes in my git repo.

Git Repo: https://github.com/Atishay007/spring-boot-with-restful-web-services

Class Name: SpringMicroservicesApplication.java



来源:https://stackoverflow.com/questions/28303758/how-to-use-yamlpropertiesfactorybean-to-load-yaml-files-using-spring-framework-4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!