Расширение языка выражения Spring в файлах xml - PullRequest
1 голос
/ 07 августа 2011

Я хочу расширить и зарегистрировать свою собственную функцию, как описано здесь:

http://static.springsource.org/spring/docs/3.0.x/reference/expressions.html см. Раздел: 6.5.11 Функции.

Однако я хочу использовать это выражениеиз весеннего XML-файла, а не в коде, представленном на странице.

Как получить ссылку на объект «StandardEvaluationContext», используемый Spring при анализе моего XML-файла?без этой весны не могу найти мою зарегистрированную функцию.

Спасибо,

Яир

Ответы [ 2 ]

2 голосов
/ 07 августа 2011

Как-то так должно начаться:

public class FunctionRegistrationBean implements BeanFactoryAware{

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        if (beanFactory instanceof ConfigurableBeanFactory) {
            ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
            cbf.setBeanExpressionResolver(new StandardBeanExpressionResolver(){
                @Override
                protected void customizeEvaluationContext(
                        StandardEvaluationContext evalContext) {
                    evalContext.registerFunction("someName", someMethod);
                    evalContext.registerFunction("someOtherName", someOtherMethod);
                }
            });
        }

    }

}

Просто зарегистрируйте этот компонент в контексте вашего приложения.

1 голос
/ 10 августа 2011

Итак, решение, которое я нашел, это:

public class DBCustomExpressionRegistration implements BeanFactoryAware {

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    if (beanFactory instanceof ConfigurableBeanFactory) {
        ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
        cbf.setBeanExpressionResolver(new StandardBeanExpressionResolver(){
            @Override
            protected void customizeEvaluationContext(
                    StandardEvaluationContext evalContext) {
                evalContext.addMethodResolver(new InfraReflectiveMethodResolver());
            }
        });
    }

}

public String getDbConfig(String param){
    Configuration configuration  = ConfigurationFactory.getConfiguration();             
    @SuppressWarnings("unchecked")
    Iterator<String> keys = configuration.getKeys();
    while(keys.hasNext()){
        String key = keys.next();
        String value = configuration.getString(key);
        String tempKey = "database.*."+param;
        if (key.matches(tempKey)){
            return value;
        }
    }

    throw new IllegalArgumentException("could find pattern for: database.<string>" + param);
}


private class InfraReflectiveMethodResolver extends ReflectiveMethodResolver {

    @Override
    public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name, List<TypeDescriptor> argumentTypes) throws AccessException {

        if ("getDbConfig".equals(name)){
            return new DBMethodExecutor();
        }
        return super.resolve(context, targetObject, name, argumentTypes);
    }

}

private class DBMethodExecutor implements MethodExecutor {

    @Override
    public TypedValue execute(EvaluationContext context, Object target, Object... arguments) throws AccessException {

        try {
            return new TypedValue(getDbConfig((String)arguments[0]), new TypeDescriptor(new MethodParameter(DBCustomExpressionRegistration.class.getDeclaredMethod("getDbConfig",new Class[] { String.class }), -1)));
        }
        catch (Exception ex) {
            throw new AccessException("Problem invoking method: getDbConfig" , ex);
        }

    }

}

}

, который вы используете из файла источника, например:

<bean id="dbCustomExpressionRegistration" class="com.db.util.DBCustomExpressionRegistration"/>

в bean-компоненте, который нуждается виспользовать функцию getDbConfig:

<property name="user" value="#{getDbConfig('username')}" />
...