Avoid early ConversionService determination in StandardBeanExpressionResolver

Closes gh-27446
This commit is contained in:
Juergen Hoeller 2021-09-21 17:42:50 +02:00
parent 49d003857d
commit 0dc5d2794f
2 changed files with 23 additions and 10 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@ -24,6 +24,7 @@ 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.core.convert.support.DefaultConversionService;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
@ -156,10 +157,10 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver {
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));
}
sec.setTypeConverter(new StandardTypeConverter(() -> {
ConversionService cs = evalContext.getBeanFactory().getConversionService();
return (cs != null ? cs : DefaultConversionService.getSharedInstance());
}));
customizeEvaluationContext(sec);
this.evaluationCache.put(evalContext, sec);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 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.
@ -16,6 +16,8 @@
package org.springframework.expression.spel.support;
import java.util.function.Supplier;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
@ -37,7 +39,7 @@ import org.springframework.util.Assert;
*/
public class StandardTypeConverter implements TypeConverter {
private final ConversionService conversionService;
private final Supplier<ConversionService> conversionService;
/**
@ -45,7 +47,7 @@ public class StandardTypeConverter implements TypeConverter {
* @see DefaultConversionService#getSharedInstance()
*/
public StandardTypeConverter() {
this.conversionService = DefaultConversionService.getSharedInstance();
this.conversionService = DefaultConversionService::getSharedInstance;
}
/**
@ -54,20 +56,30 @@ public class StandardTypeConverter implements TypeConverter {
*/
public StandardTypeConverter(ConversionService conversionService) {
Assert.notNull(conversionService, "ConversionService must not be null");
this.conversionService = () -> conversionService;
}
/**
* Create a StandardTypeConverter for the given ConversionService.
* @param conversionService a Supplier for the ConversionService to delegate to
* @since 5.3.11
*/
public StandardTypeConverter(Supplier<ConversionService> conversionService) {
Assert.notNull(conversionService, "Supplier must not be null");
this.conversionService = conversionService;
}
@Override
public boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
return this.conversionService.canConvert(sourceType, targetType);
return this.conversionService.get().canConvert(sourceType, targetType);
}
@Override
@Nullable
public Object convertValue(@Nullable Object value, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
try {
return this.conversionService.convert(value, sourceType, targetType);
return this.conversionService.get().convert(value, sourceType, targetType);
}
catch (ConversionException ex) {
throw new SpelEvaluationException(ex, SpelMessage.TYPE_CONVERSION_ERROR,