Как использовать YamlPropertiesFactoryBean для загрузки файлов YAML с помощью Spring Framework 4.1?
У меня есть приложение Spring, которое в настоящее время использует файлы *.properties, и я хочу использовать его вместо файлов YAML.
Я нашел класс YamlPropertiesFactoryBean, который, кажется, способен делать то, что мне нужно.
Моя проблема в том, что я не уверен, как использовать этот класс в моем приложении Spring (которое использует конфигурацию на основе аннотаций). Кажется, я должен настроить его в PropertySourcesPlaceholderConfigurer с помощью метода setBeanFactory.
Ранее я загружал файлы свойств с помощью @PropertySource следующим образом:
@Configuration
@PropertySource("classpath:/default.properties")
public class PropertiesConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Как включить YamlPropertiesFactoryBean в PropertySourcesPlaceholderConfigurer, чтобы я мог загружать файлы YAML напрямую? Или есть другой способ сделать это?
Благодарю.
Мое приложение использует конфигурацию на основе аннотаций, и я использую Spring Framework 4.1.4. Я нашел некоторую информацию, но она всегда указывала мне на Spring Boot, как этот.
5 ответов
С XML-конфигурацией я использовал эту конструкцию:
<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"/>
Конечно, у вас должна быть зависимость snakeyaml от вашего пути к классам во время выполнения.
Я предпочитаю XML-конфигурацию, а не Java-конфигурацию, но я считаю, что преобразовать ее не составит труда.
редактировать:
Конфигурация Java для полноты ради
@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;
}
`
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-пример-File.yml
person:
firstName: Mahmoud
middleName:Ahmed
Ссылка на мой пример на github https://github.com/JavaAdore/spring-boot-yaml-sample Так что вы можете загружать файлы yaml и вставлять значения, используя @Value()
Чтобы прочитать файл.yml в Spring, вы можете использовать следующий подход.
Например, у вас есть этот файл.yml:
section1:
key1: "value1"
key2: "value2"
section2:
key1: "value1"
key2: "value2"
Затем определите 2 Java POJO:
@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.
}
Теперь вы можете автоматически связывать эти компоненты в вашем компоненте. Например:
@Component
public class MyPropertiesAggregator {
@Autowired
private MyCustomSection1 section;
}
В случае, если вы используете Spring Boot, все будет автоматически проверено и создано:
@SpringBootApplication
public class MainBootApplication {
public static void main(String[] args) {
new SpringApplicationBuilder()
.sources(MainBootApplication.class)
.bannerMode(OFF)
.run(args);
}
}
Если вы используете JUnit, есть базовая тестовая настройка для загрузки файла YAML:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(MainBootApplication.class)
public class MyJUnitTests {
...
}
Если вы используете TestNG, есть пример конфигурации теста:
@SpringApplicationConfiguration(MainBootApplication.class)
public abstract class BaseITTest extends AbstractTestNGSpringContextTests {
....
}
Я трачу от 5 до 6 часов, чтобы понять, почему внешняя конфигурация файла yml / yaml (не application.yml) так различна. Я читал различные статьи, вопросы переполнения стека, но не получил правильный ответ.
Я застрял между ними, как будто я мог использовать пользовательское значение файла yml с помощью YamlPropertySourceLoader, но не смог использовать @Value, потому что он дает мне ошибку, например, Ошибка внедрения автопроводных зависимостей; вложенным исключением является java.lang.IllegalArgumentException: не удалось разрешить заполнитель 'fullname.firstname' в значении "${fullname.firstname}"
полное имя - это свойство в yml.
Затем я использовал "turtlesallthewaydown", указанное выше, затем наконец смог без проблем использовать @Value для файлов yaml и удалил YamlPropertySourceLoader.
Теперь я понимаю разницу между YamlPropertySourceLoader и PropertySourcesPlaceholderConfigurer, большое спасибо, однако я добавил эти изменения в мое git-репо.
Если кто-то будет искать, как загрузить файл yaml в Properties в Spring, то есть решение:
public Properties loadYaml(String fileName){
// fileName for eg is "my-settings.yaml"
YamlPropertySourceLoader ypsl = new YamlPropertySourceLoader();
PropertySource ps = ypsl.load(fileName, new ClassPathResource(fileName)).get(0);
Properties props = new Properties();
props.putAll((Map)ps.getSource());
return props;
}