将$ {my.property}评估为@Value注释

时间:2017-09-28 09:45:37

标签: java spring spring-el

长话短说:

有没有办法将${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})转换为目标类型{{1} }。

现在,我通过编写一个实现Product的类来解决这个问题,但是由于我需要通过实例化Converter<String, Product>以编程方式将字符串计算为SpEL表达式,因此它非常复杂。上。

但是有更简单的解决方案吗?是否有一个SpEL表达式放在ExpressionParser注释中,这样我就可以简单地将@Value评估为SpEL表达式了吗?

1 个答案:

答案 0 :(得分:2)

可能只是在属性值中用@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;
        }
    }
}