/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.expression;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanExpressionException;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.core.convert.ConversionService;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.support.StandardTypeConverter;
import org.springframework.expression.spel.support.StandardTypeLocator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

Standard implementation of the BeanExpressionResolver interface, parsing and evaluating Spring EL using Spring's expression module.

All beans in the containing BeanFactory are made available as predefined variables with their common bean name, including standard context beans such as "environment", "systemProperties" and "systemEnvironment".

Author:Juergen Hoeller
See Also:
Since:3.0
/** * Standard implementation of the * {@link org.springframework.beans.factory.config.BeanExpressionResolver} * interface, parsing and evaluating Spring EL using Spring's expression module. * * <p>All beans in the containing {@code BeanFactory} are made available as * predefined variables with their common bean name, including standard context * beans such as "environment", "systemProperties" and "systemEnvironment". * * @author Juergen Hoeller * @since 3.0 * @see BeanExpressionContext#getBeanFactory() * @see org.springframework.expression.ExpressionParser * @see org.springframework.expression.spel.standard.SpelExpressionParser * @see org.springframework.expression.spel.support.StandardEvaluationContext */
public class StandardBeanExpressionResolver implements BeanExpressionResolver {
Default expression prefix: "#{".
/** Default expression prefix: "#{". */
public static final String DEFAULT_EXPRESSION_PREFIX = "#{";
Default expression suffix: "}".
/** Default expression suffix: "}". */
public static final String DEFAULT_EXPRESSION_SUFFIX = "}"; private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX; private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX; private ExpressionParser expressionParser; private final Map<String, Expression> expressionCache = new ConcurrentHashMap<>(256); private final Map<BeanExpressionContext, StandardEvaluationContext> evaluationCache = new ConcurrentHashMap<>(8); private final ParserContext beanExpressionParserContext = new ParserContext() { @Override public boolean isTemplate() { return true; } @Override public String getExpressionPrefix() { return expressionPrefix; } @Override public String getExpressionSuffix() { return expressionSuffix; } };
Create a new StandardBeanExpressionResolver with default settings.
/** * Create a new {@code StandardBeanExpressionResolver} with default settings. */
public StandardBeanExpressionResolver() { this.expressionParser = new SpelExpressionParser(); }
Create a new StandardBeanExpressionResolver with the given bean class loader, using it as the basis for expression compilation.
Params:
  • beanClassLoader – the factory's bean class loader
/** * Create a new {@code StandardBeanExpressionResolver} with the given bean class loader, * using it as the basis for expression compilation. * @param beanClassLoader the factory's bean class loader */
public StandardBeanExpressionResolver(@Nullable ClassLoader beanClassLoader) { this.expressionParser = new SpelExpressionParser(new SpelParserConfiguration(null, beanClassLoader)); }
Set the prefix that an expression string starts with. The default is "#{".
See Also:
  • DEFAULT_EXPRESSION_PREFIX
/** * Set the prefix that an expression string starts with. * The default is "#{". * @see #DEFAULT_EXPRESSION_PREFIX */
public void setExpressionPrefix(String expressionPrefix) { Assert.hasText(expressionPrefix, "Expression prefix must not be empty"); this.expressionPrefix = expressionPrefix; }
Set the suffix that an expression string ends with. The default is "}".
See Also:
  • DEFAULT_EXPRESSION_SUFFIX
/** * Set the suffix that an expression string ends with. * The default is "}". * @see #DEFAULT_EXPRESSION_SUFFIX */
public void setExpressionSuffix(String expressionSuffix) { Assert.hasText(expressionSuffix, "Expression suffix must not be empty"); this.expressionSuffix = expressionSuffix; }
Specify the EL parser to use for expression parsing.

Default is a SpelExpressionParser, compatible with standard Unified EL style expression syntax.

/** * Specify the EL parser to use for expression parsing. * <p>Default is a {@link org.springframework.expression.spel.standard.SpelExpressionParser}, * compatible with standard Unified EL style expression syntax. */
public void setExpressionParser(ExpressionParser expressionParser) { Assert.notNull(expressionParser, "ExpressionParser must not be null"); this.expressionParser = expressionParser; } @Override @Nullable public Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException { if (!StringUtils.hasLength(value)) { return value; } try { Expression expr = this.expressionCache.get(value); if (expr == null) { expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext); this.expressionCache.put(value, expr); } StandardEvaluationContext sec = this.evaluationCache.get(evalContext); if (sec == null) { sec = new StandardEvaluationContext(evalContext); sec.addPropertyAccessor(new BeanExpressionContextAccessor()); sec.addPropertyAccessor(new BeanFactoryAccessor()); sec.addPropertyAccessor(new MapAccessor()); sec.addPropertyAccessor(new EnvironmentAccessor()); sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory())); sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader())); ConversionService conversionService = evalContext.getBeanFactory().getConversionService(); if (conversionService != null) { sec.setTypeConverter(new StandardTypeConverter(conversionService)); } customizeEvaluationContext(sec); this.evaluationCache.put(evalContext, sec); } return expr.getValue(sec); } catch (Throwable ex) { throw new BeanExpressionException("Expression parsing failed", ex); } }
Template method for customizing the expression evaluation context.

The default implementation is empty.

/** * Template method for customizing the expression evaluation context. * <p>The default implementation is empty. */
protected void customizeEvaluationContext(StandardEvaluationContext evalContext) { } }