parent
20be9e150c
commit
f4c1ad7ae6
|
@ -19,7 +19,6 @@ package org.springframework.expression.spel;
|
|||
import org.springframework.asm.MethodVisitor;
|
||||
import org.springframework.asm.Opcodes;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* A compilable {@link PropertyAccessor} is able to generate bytecode that represents
|
||||
|
@ -45,14 +44,10 @@ public interface CompilablePropertyAccessor extends PropertyAccessor, Opcodes {
|
|||
* Generate the bytecode that performs the access operation into the specified
|
||||
* {@link MethodVisitor} using context information from the {@link CodeFlow}
|
||||
* where necessary.
|
||||
* <p>Concrete implementations of {@code CompilablePropertyAccessor} typically
|
||||
* have access to the property name via other means (for example, supplied as
|
||||
* an argument when they were instantiated). Thus, the {@code propertyName}
|
||||
* supplied to this method may be {@code null}.
|
||||
* @param propertyName the name of the property, or {@code null} if not available
|
||||
* @param propertyName the name of the property
|
||||
* @param methodVisitor the ASM method visitor into which code should be generated
|
||||
* @param codeFlow the current state of the expression compiler
|
||||
*/
|
||||
void generateCode(@Nullable String propertyName, MethodVisitor methodVisitor, CodeFlow codeFlow);
|
||||
void generateCode(String propertyName, MethodVisitor methodVisitor, CodeFlow codeFlow);
|
||||
|
||||
}
|
||||
|
|
|
@ -213,16 +213,17 @@ public class Indexer extends SpelNodeImpl {
|
|||
if (this.indexedType == IndexedType.ARRAY) {
|
||||
return (this.exitTypeDescriptor != null);
|
||||
}
|
||||
else if (this.indexedType == IndexedType.LIST) {
|
||||
return this.children[0].isCompilable();
|
||||
SpelNodeImpl index = this.children[0];
|
||||
if (this.indexedType == IndexedType.LIST) {
|
||||
return index.isCompilable();
|
||||
}
|
||||
else if (this.indexedType == IndexedType.MAP) {
|
||||
return (this.children[0] instanceof PropertyOrFieldReference || this.children[0].isCompilable());
|
||||
return (index instanceof PropertyOrFieldReference || index.isCompilable());
|
||||
}
|
||||
else if (this.indexedType == IndexedType.OBJECT) {
|
||||
// If the string name is changing, the accessor is clearly going to change.
|
||||
// So compilation is only possible if the index expression is a StringLiteral.
|
||||
return (getChild(0) instanceof StringLiteral &&
|
||||
return (index instanceof StringLiteral &&
|
||||
this.cachedReadAccessor instanceof CompilablePropertyAccessor compilablePropertyAccessor &&
|
||||
compilablePropertyAccessor.isCompilable());
|
||||
}
|
||||
|
@ -238,6 +239,7 @@ public class Indexer extends SpelNodeImpl {
|
|||
}
|
||||
|
||||
SpelNodeImpl index = this.children[0];
|
||||
|
||||
if (this.indexedType == IndexedType.ARRAY) {
|
||||
int insn = switch (this.exitTypeDescriptor) {
|
||||
case "D" -> {
|
||||
|
@ -313,9 +315,14 @@ public class Indexer extends SpelNodeImpl {
|
|||
}
|
||||
|
||||
else if (this.indexedType == IndexedType.OBJECT) {
|
||||
if (!(index instanceof StringLiteral stringLiteral)) {
|
||||
throw new IllegalStateException(
|
||||
"Index expression must be a StringLiteral, but was: " + index.getClass().getName());
|
||||
}
|
||||
CompilablePropertyAccessor compilablePropertyAccessor = (CompilablePropertyAccessor) this.cachedReadAccessor;
|
||||
Assert.state(compilablePropertyAccessor != null, "No cached read accessor");
|
||||
compilablePropertyAccessor.generateCode(null, mv, cf);
|
||||
String propertyName = (String) stringLiteral.getLiteralValue().getValue();
|
||||
compilablePropertyAccessor.generateCode(propertyName, mv, cf);
|
||||
}
|
||||
|
||||
cf.pushDescriptor(this.exitTypeDescriptor);
|
||||
|
|
|
@ -712,7 +712,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void generateCode(@Nullable String propertyName, MethodVisitor mv, CodeFlow cf) {
|
||||
public void generateCode(String propertyName, MethodVisitor mv, CodeFlow cf) {
|
||||
Class<?> publicDeclaringClass = this.member.getDeclaringClass();
|
||||
if (!Modifier.isPublic(publicDeclaringClass.getModifiers()) && this.originalMethod != null) {
|
||||
publicDeclaringClass = ReflectionHelper.findPublicDeclaringClass(this.originalMethod);
|
||||
|
|
Loading…
Reference in New Issue