【问题标题】:Custom type conversion of property values属性值的自定义类型转换
【发布时间】:2017-02-26 02:51:43
【问题描述】:

我有一个 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 {...}

现在,intFieldstringField 按预期使用所需的值进行初始化,但 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。

【问题讨论】:

  • 您是否尝试过添加您的自定义转换器?应该是实现Converter的类,更多详情stackoverflow.com/questions/34239585/…
  • 你为什么不把它像豆子一样注入?
  • @freakman 我还没有尝试过,我是 Spring 新手,对事情感到困惑。我试试看
  • @grape_mao 但我希望customField 可以通过属性文件进行配置,也就是说,如果我以后选择使用CustomInterface 的不同实现,我可以只更改属性文件...

标签: java spring spring-boot type-conversion properties-file


【解决方案1】:

要解决您的直接问题,您需要查看 bean 上的 @PostConstruct 选项。这将允许您在 bean 可用于上下文之前对事物采取行动。

@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 的实例,该实例可作为Spring ApplicationContext 上的一个bean 使用。为此,您将改为执行以下操作:

@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 的实例化 bean,您可以让 Spring 自动装配到其他对象中。

【讨论】:

  • 感谢您的精彩回答。我已经尝试了您建议的两种解决方案,它们都运行良好。 (虽然第一个更冗长,但它提供了在 ${...} 值字符串上按 ctrl+click(intellij 想法)的能力,这会将您直接带到 .properties 文件中的属性。我会接受您的回答,尽管我可能会最终不会使用它,因为我的自定义类型可以具有构造函数参数,所以我可能不得不完全不同地处理它。
  • @radoh 我意识到这是一个“有点”老问题,但很高兴看到你发布一个关于你最终如何设法包含这些构造函数参数的答案......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
  • 1970-01-01
  • 2016-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多