将$ {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; } } }