DEV Community

Salad Lam
Salad Lam

Posted on

Query beans by using Spring Expression Language (SpEL)

There is a getBeanExpressionResolver() method in ConfigurableBeanFactory interface. Following is the actual implementation.

public class StandardBeanExpressionResolver implements BeanExpressionResolver {

    @Override
    @Nullable
    public Object evaluate(@Nullable String value, BeanExpressionContext beanExpressionContext) 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(beanExpressionContext);
            if (sec == null) {
                sec = new StandardEvaluationContext(beanExpressionContext);
                sec.addPropertyAccessor(new BeanExpressionContextAccessor());
                sec.addPropertyAccessor(new BeanFactoryAccessor());
                sec.addPropertyAccessor(new MapAccessor());
                sec.addPropertyAccessor(new EnvironmentAccessor());
                sec.setBeanResolver(new BeanFactoryResolver(beanExpressionContext.getBeanFactory()));
                sec.setTypeLocator(new StandardTypeLocator(beanExpressionContext.getBeanFactory().getBeanClassLoader()));
                sec.setTypeConverter(new StandardTypeConverter(() -> {
                    ConversionService cs = beanExpressionContext.getBeanFactory().getConversionService();
                    return (cs != null ? cs : DefaultConversionService.getSharedInstance());
                }));
                customizeEvaluationContext(sec);
                this.evaluationCache.put(beanExpressionContext, sec);
            }
            return expr.getValue(sec);
        }
        catch (Throwable ex) {
            throw new BeanExpressionException("Expression parsing failed", ex);
        }
    }

    // ...
}
Enter fullscreen mode Exit fullscreen mode

org.springframework.expression.PropertyAccessor interface

To get/set value/instance by class's method/property on a particular type of object.

org.springframework.expression.BeanResolver interface

For lookup the actual bean when following symbol exists in expression

  • "&" get the FactoryBean itself instead of actual bean
  • "@" bean reference

org.springframework.expression.TypeLocator interface

For lookup the actual class instance when package information is omitted in expression. For example the expression "T(String)", the actual class "java.lang.String" will be returned.

org.springframework.expression.TypeConverter interface

For converting an instance of a type to other, such as java.time.ZonedDateTime to java.util.Calendar.

Example

Following is a bean class

@Service("applicationDateTimeService")
public class ApplicationDateTimeService {

    @Override
    public LocalDateTime getCurrentLocalDateTime() {
        return LocalDateTime.now();
    }

}
Enter fullscreen mode Exit fullscreen mode

Access the bean

ConfigurableBeanFactory beanfactory;
// code of inject ConfigurableBeanFactory
String result = (String) beanfactory.getBeanExpressionResolver().evaluate("#{applicationDateTimeService.currentLocalDateTime.toString()}", new BeanExpressionContext(beanfactory, null));
// 2025-01-16T18:36:07.012526300
Enter fullscreen mode Exit fullscreen mode

In this example, "#{applicationDateTimeService}" and "#{@applicationDateTimeService}" refer to the same bean because the root object is BeanFactory instance.

Top comments (0)