Polishing

This commit is contained in:
Juergen Hoeller 2018-03-14 17:24:58 +01:00
parent 356ef45e99
commit 3988dd9ebb
4 changed files with 36 additions and 26 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 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.
@ -64,8 +64,7 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver {
private final Map<String, Expression> expressionCache = new ConcurrentHashMap<>(256);
private final Map<BeanExpressionContext, StandardEvaluationContext> evaluationCache =
new ConcurrentHashMap<>(8);
private final Map<BeanExpressionContext, StandardEvaluationContext> evaluationCache = new ConcurrentHashMap<>(8);
private final ParserContext beanExpressionParserContext = new ParserContext() {
@Override
@ -145,8 +144,7 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver {
}
StandardEvaluationContext sec = this.evaluationCache.get(evalContext);
if (sec == null) {
sec = new StandardEvaluationContext();
sec.setRootObject(evalContext);
sec = new StandardEvaluationContext(evalContext);
sec.addPropertyAccessor(new BeanExpressionContextAccessor());
sec.addPropertyAccessor(new BeanFactoryAccessor());
sec.addPropertyAccessor(new MapAccessor());

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 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.
@ -57,7 +57,8 @@ public class MethodReference extends SpelNodeImpl {
private final boolean nullSafe;
private String originalPrimitiveExitTypeDescriptor = null;
@Nullable
private String originalPrimitiveExitTypeDescriptor;
@Nullable
private volatile CachedMethodExecutor cachedExecutor;
@ -311,11 +312,11 @@ public class MethodReference extends SpelNodeImpl {
// Nothing on the stack but something is needed
cf.loadTarget(mv);
}
if ((descriptor != null || !isStaticMethod) && nullSafe) {
if ((descriptor != null || !isStaticMethod) && this.nullSafe) {
mv.visitInsn(DUP);
skipIfNull = new Label();
Label continueLabel = new Label();
mv.visitJumpInsn(IFNONNULL,continueLabel);
mv.visitJumpInsn(IFNONNULL, continueLabel);
CodeFlow.insertCheckCast(mv, this.exitTypeDescriptor);
mv.visitJumpInsn(GOTO, skipIfNull);
mv.visitLabel(continueLabel);
@ -329,7 +330,7 @@ public class MethodReference extends SpelNodeImpl {
CodeFlow.insertBoxIfNecessary(mv, descriptor.charAt(0));
}
String classDesc = null;
String classDesc;
if (Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
classDesc = method.getDeclaringClass().getName().replace('.', '/');
}
@ -339,20 +340,19 @@ public class MethodReference extends SpelNodeImpl {
classDesc = publicDeclaringClass.getName().replace('.', '/');
}
if (!isStaticMethod) {
if (descriptor == null || !descriptor.substring(1).equals(classDesc)) {
CodeFlow.insertCheckCast(mv, "L" + classDesc);
}
if (!isStaticMethod && (descriptor == null || !descriptor.substring(1).equals(classDesc))) {
CodeFlow.insertCheckCast(mv, "L" + classDesc);
}
generateCodeForArguments(mv, cf, method, this.children);
mv.visitMethodInsn((isStaticMethod ? INVOKESTATIC : INVOKEVIRTUAL), classDesc, method.getName(),
CodeFlow.createSignatureDescriptor(method), method.getDeclaringClass().isInterface());
cf.pushDescriptor(this.exitTypeDescriptor);
if (originalPrimitiveExitTypeDescriptor != null) {
if (this.originalPrimitiveExitTypeDescriptor != null) {
// The output of the accessor will be a primitive but from the block above it might be null,
// so to have a 'common stack' element at skipIfNull target we need to box the primitive
CodeFlow.insertBoxIfNecessary(mv, originalPrimitiveExitTypeDescriptor);
CodeFlow.insertBoxIfNecessary(mv, this.originalPrimitiveExitTypeDescriptor);
}
if (skipIfNull != null) {
mv.visitLabel(skipIfNull);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 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.
@ -52,10 +52,11 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
private final boolean nullSafe;
private String originalPrimitiveExitTypeDescriptor = null;
private final String name;
@Nullable
private String originalPrimitiveExitTypeDescriptor;
@Nullable
private volatile PropertyAccessor cachedReadAccessor;
@ -341,23 +342,26 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
if (!(accessorToUse instanceof CompilablePropertyAccessor)) {
throw new IllegalStateException("Property accessor is not compilable: " + accessorToUse);
}
Label skipIfNull = null;
if (nullSafe) {
if (this.nullSafe) {
mv.visitInsn(DUP);
skipIfNull = new Label();
Label continueLabel = new Label();
mv.visitJumpInsn(IFNONNULL,continueLabel);
mv.visitJumpInsn(IFNONNULL, continueLabel);
CodeFlow.insertCheckCast(mv, this.exitTypeDescriptor);
mv.visitJumpInsn(GOTO, skipIfNull);
mv.visitLabel(continueLabel);
}
((CompilablePropertyAccessor) accessorToUse).generateCode(this.name, mv, cf);
cf.pushDescriptor(this.exitTypeDescriptor);
if (originalPrimitiveExitTypeDescriptor != null) {
if (this.originalPrimitiveExitTypeDescriptor != null) {
// The output of the accessor is a primitive but from the block above it might be null,
// so to have a common stack element type at skipIfNull target it is necessary
// to box the primitive
CodeFlow.insertBoxIfNecessary(mv, originalPrimitiveExitTypeDescriptor);
CodeFlow.insertBoxIfNecessary(mv, this.originalPrimitiveExitTypeDescriptor);
}
if (skipIfNull != null) {
mv.visitLabel(skipIfNull);

View File

@ -57,7 +57,7 @@ import org.springframework.util.Assert;
*/
public class StandardEvaluationContext implements EvaluationContext {
private TypedValue rootObject = TypedValue.NULL;
private TypedValue rootObject;
@Nullable
private volatile List<PropertyAccessor> propertyAccessors;
@ -87,12 +87,20 @@ public class StandardEvaluationContext implements EvaluationContext {
private final Map<String, Object> variables = new HashMap<>();
/**
* Create a {@code StandardEvaluationContext} with a null root object.
*/
public StandardEvaluationContext() {
setRootObject(null);
this.rootObject = TypedValue.NULL;
}
/**
* Create a {@code StandardEvaluationContext} with the given root object.
* @param rootObject the root object to use
* @see #setRootObject
*/
public StandardEvaluationContext(Object rootObject) {
setRootObject(rootObject);
this.rootObject = new TypedValue(rootObject);
}