2016-10-17 5 views
0

У меня есть myapp.properties файл с парами ключ-значение определяется как:Пользовательские преобразования тип собственности значения

prefix.int-field=123 
prefix.string-field=asdf 
prefix.custom-type-field=my.package.CustomType 

Я пытаюсь внедрить эти свойства с помощью @Value аннотацию в следующем классе:

@PropertySource(value = "classpath:myapp.properties") 
@Component 
class MySettings { 
    @Value("${prefix.int-field}") 
    private int intField; 

    @Value("${prefix.string-field}") 
    private String stringField; 

    @Value("${prefix.custom-type-field}") // <-- this is the problem 
    private CustomInterface customField; 
} 

class CustomType implements CustomInterface {...} 

interface CustomInterface {...} 

Теперь intField и stringField инициализируются с требуемыми значениями, как и ожидалось, но customField бросает исключение:

Caused by: java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [my.package.CustomInterface]: no matching editors or conversion strategy found 
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:303) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE] 
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:125) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE] 
    at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:61) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE] 

Как преобразовать значения свойств текста в мой пользовательский тип?

Я попытался проконсультироваться с documentation, но я не вижу правильного пути его выполнения. Я использую Spring Boot 1.3.6.

+1

Вы пытались добавить свой собственный конвертер? Это должен быть класс, реализующий Converter , подробнее http://stackoverflow.com/questions/34239585/how-to-register-custom-converters-in-spring-boot – freakman

+0

Почему бы вам просто не ввести это как фасоль? –

+0

@freakman Я еще не пробовал, я новичок в Spring и смущен. Я дам ему выстрел – radoh

ответ

1

Чтобы решить вашу проблему, вы хотите посмотреть опцию @PostConstruct на фасоль. Это позволит вам действовать по вещам, пока компонент не станет доступен для контекста.

@PropertySource(value = "classpath:myapp.properties") 
@Component 
class MySettings { 
    @Value("${prefix.int-field}") 
    private int intField; 

    @Value("${prefix.string-field}") 
    private String stringField; 

    @Value("${prefix.custom-type-field}") 
    private String customFieldType; 

    private CustomInterface customField; 

    @PostConstruct 
    public void init() { 
     customField = (CustomInterface) Class.forName(customFieldType).newInstance(); // short form... will need checks that it finds the class and can create a new instance 
    } 
} 

class CustomType implements CustomInterface {...} 

interface CustomInterface {...} 

Мне интересно, если вы, возможно, захотите использовать @Configuration аннотацию класса и создать экземпляр CustomInterface, которая доступна в виде боба на весеннем ApplicationContext. Чтобы сделать это, вы бы вместо того, чтобы сделать что-то вроде этого:

@Component 
@ConfigurationProperties(prefix = "prefix") 
class MySettings { 
    private int intField; 

    private String stringField; 

    private String customTypeField; 

    // getters and setters 
} 

Это будет затем использоваться в @Configuration классе:

@Configuration 
class MyConfiguration { 
    @Bean 
    public CustomInterface customInterface(MySettings mySettings) { 
     return (CustomInterface) Class.forName(mySettings.getCustomTypeField()).newInstance(); 
    } 
} 

На данный момент вы бы сейчас проиллюстрированный компонент для CustomInterface, что вы можете иметь Spring autowire в другие объекты.

+0

Спасибо за хороший ответ. Я попробовал 2 предложенных вами решения, и они оба работают хорошо. (хотя первый из них более подробный, он предлагает возможность ctrl + click (intellij idea) в строке значения $ $ ... ... ', которая возвращает вас прямо к свойству в файле .properties. принимайте ваш ответ, хотя я не могу его использовать, поскольку мои пользовательские типы могут иметь параметры конструктора, поэтому мне, вероятно, придется подойти к нему совершенно по-другому. – radoh