将 ${my.property} 评估为 @Value 注释中的 SpEL 表达式



长话短说:

有没有办法在不使用转换器的情况下将${my.property}产生的字符串解释为@Value注释中的 SpEL 表达式,例如@Value("#{${my.property}})?


有一个抽象工厂(简化),它允许我构建一些公共对象,这些对象是系统配置的一部分。

@Component
public class Factory {
public Product makeVal(int x) { return new Product(5); }
}

为了更灵活,我想让用户在app.properties文件中编写 SpEL 表达式,以便可以直接访问工厂:

my.property = @Factory.makeVal(12)

现在,在需要此属性的类中,为了实现我的目标,我编写了以下代码。

@Value("#{${my.property}}")
private Product obj;

我认为${my.property}将被宏观扩展,然后由#{}评估为相应的 SpEL 表达式,@Factory.makeVal(12)上面的例子。不幸的是,情况并非如此,加载 Spring 上下文会导致错误,指出它无法将字符串(属性的值${my.property})转换为目标类型Product

现在,我通过编写一个实现Converter<String, Product>的类来解决这个问题,但它非常复杂,因为我需要在那里通过实例化ExpressionParser等以编程方式将字符串评估为 SpEL 表达式。

但是有更简单的解决方案吗?请问是否有一个 SpEL 表达式可以放入@Value注释中,让我简单地将${my.property}本身评估为 SpEL 表达式?

也许这只是将@Factory替换为属性值中的factory的问题。这个测试对我来说通过了:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { SpelTest.Config.class })
public class SpelTest
{
@Value("#{${my.property}}")
Product _product;
@Test
public void evaluating_spel_from_property_value() throws Exception
{
Assert.assertEquals(1234, _product.value);
}
@Component
public static class Factory
{
public Product makeVal(int x) { return new Product(x); }
}
public static class Product
{
public final int value;
public Product(final int value) { this.value = value; }
}
@Configuration
@ComponentScan(basePackageClasses = SpelTest.class)
public static class Config
{
@Bean
public Factory factory() { return new Factory(); }
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
final PropertySourcesPlaceholderConfigurer psc = new PropertySourcesPlaceholderConfigurer();
final MutablePropertySources sources = new MutablePropertySources();
sources.addFirst(new MockPropertySource()
.withProperty("my.property", 
"factory.makeVal(1234)"));
psc.setPropertySources(sources);
return psc;
}
}
}    

最新更新