Spring 3:禁用对bean属性值的SpEL评估?

时间:2010-12-16 17:22:10

标签: java spring javabeans

我们正在将我们的应用程序从Spring 2.5更新到3.0,并且我们遇到了新的SpEL评估bean属性的问题。

我们一直在一个模块中使用内部模板语法,不幸的是,它使用与SpEL相同的“#{xyz}”标记。我们有一些bean将包含这些表达式的字符串作为属性,但是spring假定它们是SpEL表达式,并在尝试实例化bean时抛出SpelEvaluationException。

e.g。

<bean id="templatingEngine" class="com.foo.TemplatingEngine">
   <property name="barTemplate" value="user=#{uid}&country=#{cty}"/>
</bean>

是否可以禁用SpEL评估,理想情况下是每个bean,但是对于整个应用程序上下文也是如此?

或者有办法逃避价值吗?

谢谢, 斯蒂芬

3 个答案:

答案 0 :(得分:4)

通过调用传入null的bean工厂setBeanExpressionResolver方法完全禁用SpEL评估。您可以定义BeanFactoryPostProcessor来执行此操作。

public class DisableSpel implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(
        ConfigurableListableBeanFactory beanFactory)
        throws BeansException
    {
        beanFactory.setBeanExpressionResolver(null);
    }
}

然后在应用程序上下文中定义此bean。

<bean class="com.example.spel.DisableSpel"/>

答案 1 :(得分:2)

您可以做的是重新定义表达式语言分隔符。

我想说这样做的方法是通过一个实现BeanFactoryPostProcessor的特殊bean(感谢Jim Huang的灵感):

public class ExpressionTokensRedefiner implements BeanFactoryPostProcessor{

    private BeanExpressionResolver beanExpressionResolver;

    public void setBeanExpressionResolver(
        final BeanExpressionResolver beanExpressionResolver){
        this.beanExpressionResolver = beanExpressionResolver;
    }

    @Override
    public void postProcessBeanFactory(
        final ConfigurableListableBeanFactory beanFactory)
        throws BeansException{
        beanFactory.setBeanExpressionResolver(createResolver());
    }

    private String expressionPrefix = "${";
    private String expressionSuffix = "}";

    public void setExpressionPrefix(final String expressionPrefix){
        this.expressionPrefix = expressionPrefix;
    }
    public void setExpressionSuffix(final String expressionSuffix){
        this.expressionSuffix = expressionSuffix;
    }

    private BeanExpressionResolver createResolver(){
        if(beanExpressionResolver == null){
            final StandardBeanExpressionResolver resolver =
                new StandardBeanExpressionResolver();
            resolver.setExpressionPrefix(expressionPrefix);
            resolver.setExpressionSuffix(expressionSuffix);
            return resolver;
        } else{
            return beanExpressionResolver;
        }
    }

}

将它定义为这样的bean:

<bean class="foo.bar.ExpressionTokensRedefiner">
    <property name="expressionPrefix" value="[[" />
    <property name="expressionSuffix" value="]]" />
</bean>

或者像这样:

<!-- this will use the default tokens ${ and } -->
<bean class="foo.bar.ExpressionTokensRedefiner" />

或使用自定义解析器:

<bean class="foo.bar.ExpressionTokensRedefiner">
    <property name="beanExpressionResolver">
        <bean class="foo.bar.CustomExpressionResolver" />
    </property>
</bean>

现在您可以保持定义不变,如果您想使用SpEL,请使用新的分隔符。

编辑:现在我测试了它,它确实有效。

<bean class="foo.bar.ExpressionTokensRedefiner">
    <property name="expressionPrefix" value="[[" />
    <property name="expressionSuffix" value="]]" />
</bean>


<bean class="foo.bar.FooFritz">
    <property name="fizz" value="[[ systemProperties['user.home'] ]]"></property>
    <property name="fozz" value="[[ systemProperties['java.io.tmpdir'] ]]"></property>
            <!-- this is what it would normally choke on -->
    <property name="fazz" value="#{ boom() }"></property>
</bean>

测试代码:

final ConfigurableApplicationContext context =
    new ClassPathXmlApplicationContext("classpath:foo/bar/ctx.xml");
context.refresh();
final FooFritz fooFritz = context.getBean(FooFritz.class);
System.out.println(fooFritz.getFizz());
System.out.println(fooFritz.getFozz());
System.out.println(fooFritz.getFazz());

输出:

  

/家庭/ seanizer
  / tmp目录
  #{boom()}

答案 2 :(得分:0)

我不是一个轻拍,但这是一个帮助。

https://issues.apache.org/jira/browse/CAMEL-2599