将$ {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的类来解决这个问题,但是它非常复杂,因为我需要通过实例化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; } } }