|
17 | 17 | package org.springframework.expression.spel.ast;
|
18 | 18 |
|
19 | 19 | import java.lang.reflect.Constructor;
|
20 |
| -import java.lang.reflect.Field; |
21 |
| -import java.lang.reflect.Member; |
22 |
| -import java.lang.reflect.Method; |
23 |
| -import java.lang.reflect.Modifier; |
24 | 20 | import java.util.Collection;
|
25 | 21 | import java.util.List;
|
26 | 22 | import java.util.Map;
|
|
35 | 31 | import org.springframework.expression.TypeConverter;
|
36 | 32 | import org.springframework.expression.TypedValue;
|
37 | 33 | import org.springframework.expression.spel.CodeFlow;
|
| 34 | +import org.springframework.expression.spel.CompilablePropertyAccessor; |
38 | 35 | import org.springframework.expression.spel.ExpressionState;
|
39 | 36 | import org.springframework.expression.spel.SpelEvaluationException;
|
40 | 37 | import org.springframework.expression.spel.SpelMessage;
|
@@ -223,10 +220,11 @@ else if (this.indexedType == IndexedType.MAP) {
|
223 | 220 | return (this.children[0] instanceof PropertyOrFieldReference || this.children[0].isCompilable());
|
224 | 221 | }
|
225 | 222 | else if (this.indexedType == IndexedType.OBJECT) {
|
226 |
| - // If the string name is changing, the accessor is clearly going to change (so no compilation possible) |
227 |
| - return (this.cachedReadAccessor != null && |
228 |
| - this.cachedReadAccessor instanceof ReflectivePropertyAccessor.OptimalPropertyAccessor && |
229 |
| - getChild(0) instanceof StringLiteral); |
| 223 | + // If the string name is changing, the accessor is clearly going to change. |
| 224 | + // So compilation is only possible if the index expression is a StringLiteral. |
| 225 | + return (getChild(0) instanceof StringLiteral && |
| 226 | + this.cachedReadAccessor instanceof CompilablePropertyAccessor compilablePropertyAccessor && |
| 227 | + compilablePropertyAccessor.isCompilable()); |
230 | 228 | }
|
231 | 229 | return false;
|
232 | 230 | }
|
@@ -315,30 +313,9 @@ else if (this.indexedType == IndexedType.MAP) {
|
315 | 313 | }
|
316 | 314 |
|
317 | 315 | else if (this.indexedType == IndexedType.OBJECT) {
|
318 |
| - ReflectivePropertyAccessor.OptimalPropertyAccessor accessor = |
319 |
| - (ReflectivePropertyAccessor.OptimalPropertyAccessor) this.cachedReadAccessor; |
320 |
| - Assert.state(accessor != null, "No cached read accessor"); |
321 |
| - Member member = accessor.member; |
322 |
| - boolean isStatic = Modifier.isStatic(member.getModifiers()); |
323 |
| - String classDesc = member.getDeclaringClass().getName().replace('.', '/'); |
324 |
| - |
325 |
| - if (!isStatic) { |
326 |
| - if (descriptor == null) { |
327 |
| - cf.loadTarget(mv); |
328 |
| - } |
329 |
| - if (descriptor == null || !classDesc.equals(descriptor.substring(1))) { |
330 |
| - mv.visitTypeInsn(CHECKCAST, classDesc); |
331 |
| - } |
332 |
| - } |
333 |
| - |
334 |
| - if (member instanceof Method method) { |
335 |
| - mv.visitMethodInsn((isStatic? INVOKESTATIC : INVOKEVIRTUAL), classDesc, member.getName(), |
336 |
| - CodeFlow.createSignatureDescriptor(method), false); |
337 |
| - } |
338 |
| - else { |
339 |
| - mv.visitFieldInsn((isStatic ? GETSTATIC : GETFIELD), classDesc, member.getName(), |
340 |
| - CodeFlow.toJvmDescriptor(((Field) member).getType())); |
341 |
| - } |
| 316 | + CompilablePropertyAccessor compilablePropertyAccessor = (CompilablePropertyAccessor) this.cachedReadAccessor; |
| 317 | + Assert.state(compilablePropertyAccessor != null, "No cached read accessor"); |
| 318 | + compilablePropertyAccessor.generateCode(null, mv, cf); |
342 | 319 | }
|
343 | 320 |
|
344 | 321 | cf.pushDescriptor(this.exitTypeDescriptor);
|
@@ -600,10 +577,8 @@ public TypedValue getValue() {
|
600 | 577 | Indexer.this.cachedReadAccessor = accessor;
|
601 | 578 | Indexer.this.cachedReadName = this.name;
|
602 | 579 | Indexer.this.cachedReadTargetType = targetObjectRuntimeClass;
|
603 |
| - if (accessor instanceof ReflectivePropertyAccessor.OptimalPropertyAccessor optimalAccessor) { |
604 |
| - Member member = optimalAccessor.member; |
605 |
| - Indexer.this.exitTypeDescriptor = CodeFlow.toDescriptor(member instanceof Method method ? |
606 |
| - method.getReturnType() : ((Field) member).getType()); |
| 580 | + if (accessor instanceof CompilablePropertyAccessor compilablePropertyAccessor) { |
| 581 | + Indexer.this.exitTypeDescriptor = CodeFlow.toDescriptor(compilablePropertyAccessor.getPropertyType()); |
607 | 582 | }
|
608 | 583 | return accessor.read(this.evaluationContext, this.targetObject, this.name);
|
609 | 584 | }
|
|
0 commit comments