Class ReflectiveIndexAccessor
- All Implemented Interfaces:
- Opcodes,- IndexAccessor,- CompilableIndexAccessor,- TargetedAccessor
IndexAccessor
 that uses reflection to read from and optionally write to an indexed structure
 of a target object.
 The indexed structure can be accessed through a public read-method (when being read) or a public write-method (when being written). The relationship between the read-method and write-method is based on a convention that is applicable for typical implementations of indexed structures. See the example below for details.
ReflectiveIndexAccessor also implements CompilableIndexAccessor
 in order to support compilation to bytecode for read access. Note, however,
 that the configured read-method must be invokable via a public class or public
 interface for compilation to succeed.
 
Example
The FruitMap class (the targetType) represents a structure
 that is indexed via the Color enum (the indexType). The name
 of the read-method is "getFruit", and that method returns a
 String (the indexedValueType). The name of the write-method
 is "setFruit", and that method accepts a Color enum (the
 indexType) and a String (the indexedValueType which
 must match the return type of the read-method).
 
A read-only IndexAccessor for FruitMap can be created via
 new ReflectiveIndexAccessor(FruitMap.class, Color.class, "getFruit").
 With that accessor registered and a FruitMap registered as a variable
 named #fruitMap, the SpEL expression #fruitMap[T(example.Color).RED]
 will evaluate to "cherry".
 
A read-write IndexAccessor for FruitMap can be created via
 new ReflectiveIndexAccessor(FruitMap.class, Color.class, "getFruit", "setFruit").
 With that accessor registered and a FruitMap registered as a variable
 named #fruitMap, the SpEL expression
 #fruitMap[T(example.Color).RED] = 'strawberry' can be used to change
 the fruit mapping for the color red from "cherry" to "strawberry".
 
 package example;
 public enum Color {
     RED, ORANGE, YELLOW
 }
 
 public class FruitMap {
     private final Map<Color, String> map = new HashMap<>();
     public FruitMap() {
         this.map.put(Color.RED, "cherry");
         this.map.put(Color.ORANGE, "orange");
         this.map.put(Color.YELLOW, "banana");
     }
     public String getFruit(Color color) {
         return this.map.get(color);
     }
     public void setFruit(Color color, String fruit) {
         this.map.put(color, fruit);
     }
 }- Since:
- 6.2
- Author:
- Sam Brannen
- See Also:
- 
Field SummaryFields inherited from interface org.springframework.asm.OpcodesAALOAD, AASTORE, ACC_ABSTRACT, ACC_ANNOTATION, ACC_BRIDGE, ACC_DEPRECATED, ACC_ENUM, ACC_FINAL, ACC_INTERFACE, ACC_MANDATED, ACC_MODULE, ACC_NATIVE, ACC_OPEN, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_RECORD, ACC_STATIC, ACC_STATIC_PHASE, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_SYNTHETIC, ACC_TRANSIENT, ACC_TRANSITIVE, ACC_VARARGS, ACC_VOLATILE, ACONST_NULL, ALOAD, ANEWARRAY, ARETURN, ARRAYLENGTH, ASM10_EXPERIMENTAL, ASM4, ASM5, ASM6, ASM7, ASM8, ASM9, ASTORE, ATHROW, BALOAD, BASTORE, BIPUSH, CALOAD, CASTORE, CHECKCAST, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DMUL, DNEG, DOUBLE, DREM, DRETURN, DSTORE, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F_APPEND, F_CHOP, F_FULL, F_NEW, F_SAME, F_SAME1, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FLOAT, FMUL, FNEG, FREM, FRETURN, FSTORE, FSUB, GETFIELD, GETSTATIC, GOTO, H_GETFIELD, H_GETSTATIC, H_INVOKEINTERFACE, H_INVOKESPECIAL, H_INVOKESTATIC, H_INVOKEVIRTUAL, H_NEWINVOKESPECIAL, H_PUTFIELD, H_PUTSTATIC, I2B, I2C, I2D, I2F, I2L, I2S, IADD, IALOAD, IAND, IASTORE, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, ICONST_M1, IDIV, IF_ACMPEQ, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, IFNONNULL, IFNULL, IINC, ILOAD, IMUL, INEG, INSTANCEOF, INTEGER, INVOKEDYNAMIC, INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC, INVOKEVIRTUAL, IOR, IREM, IRETURN, ISHL, ISHR, ISTORE, ISUB, IUSHR, IXOR, JSR, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, LCONST_0, LCONST_1, LDC, LDIV, LLOAD, LMUL, LNEG, LONG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSUB, LUSHR, LXOR, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, NEW, NEWARRAY, NOP, NULL, POP, POP2, PUTFIELD, PUTSTATIC, RET, RETURN, SALOAD, SASTORE, SIPUSH, SOURCE_DEPRECATED, SOURCE_MASK, SWAP, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_SHORT, TABLESWITCH, TOP, UNINITIALIZED_THIS, V_PREVIEW, V1_1, V1_2, V1_3, V1_4, V1_5, V1_6, V1_7, V1_8, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V9
- 
Constructor SummaryConstructorsConstructorDescriptionReflectiveIndexAccessor(Class<?> targetType, Class<?> indexType, String readMethodName) Construct a newReflectiveIndexAccessorfor read-only access.ReflectiveIndexAccessor(Class<?> targetType, Class<?> indexType, String readMethodName, @Nullable String writeMethodName) Construct a newReflectiveIndexAccessorfor read-write access.
- 
Method SummaryModifier and TypeMethodDescriptionbooleancanRead(EvaluationContext context, Object target, Object index) Returntrueif the suppliedtargetandindexcan be assigned to thetargetTypeandindexTypeconfigured via the constructor.booleancanWrite(EvaluationContext context, Object target, Object index) Returntrueif a write-method has been configured andcanRead(org.springframework.expression.EvaluationContext, java.lang.Object, java.lang.Object)returnstruefor the same arguments.voidgenerateCode(SpelNode index, MethodVisitor mv, CodeFlow cf) Generate bytecode that performs the operation for reading the index.Class<?> Get the return type of the configured read-method.Class<?>[]Return an array containing thetargetTypeconfigured via the constructor.booleanDetermine if thisIndexAccessoris currently suitable for compilation.read(EvaluationContext context, Object target, Object index) Invoke the configured read-method via reflection and return the result wrapped in aTypedValue.voidInvoke the configured write-method via reflection.
- 
Constructor Details- 
ReflectiveIndexAccessorConstruct a newReflectiveIndexAccessorfor read-only access.See class-level documentation for further details and an example. - Parameters:
- targetType- the type of indexed structure which serves as the target of index operations
- indexType- the type of index used to read from the indexed structure
- readMethodName- the name of the method used to read from the indexed structure
 
- 
ReflectiveIndexAccessorpublic ReflectiveIndexAccessor(Class<?> targetType, Class<?> indexType, String readMethodName, @Nullable String writeMethodName) Construct a newReflectiveIndexAccessorfor read-write access.See class-level documentation for further details and an example. - Parameters:
- targetType- the type of indexed structure which serves as the target of index operations
- indexType- the type of index used to read from or write to the indexed structure
- readMethodName- the name of the method used to read from the indexed structure
- writeMethodName- the name of the method used to write to the indexed structure, or- nullif writing is not supported
 
 
- 
- 
Method Details- 
getSpecificTargetClassesReturn an array containing thetargetTypeconfigured via the constructor.- Specified by:
- getSpecificTargetClassesin interface- TargetedAccessor
- Returns:
- an array of classes that this accessor is suitable for
 (or nullor an empty array if a generic accessor)
 
- 
canReadReturntrueif the suppliedtargetandindexcan be assigned to thetargetTypeandindexTypeconfigured via the constructor.Considers primitive wrapper classes as assignable to the corresponding primitive types. - Specified by:
- canReadin interface- IndexAccessor
- Parameters:
- context- the evaluation context in which the access is being attempted
- target- the target object upon which the index is being accessed
- index- the index being accessed
- Returns:
- trueif this index accessor is able to read the index
 
- 
readInvoke the configured read-method via reflection and return the result wrapped in aTypedValue.- Specified by:
- readin interface- IndexAccessor
- Parameters:
- context- the evaluation context in which the access is being attempted
- target- the target object upon which the index is being accessed
- index- the index being accessed
- Returns:
- a TypedValue object wrapping the index value read and a type descriptor for the value
 
- 
canWriteReturntrueif a write-method has been configured andcanRead(org.springframework.expression.EvaluationContext, java.lang.Object, java.lang.Object)returnstruefor the same arguments.- Specified by:
- canWritein interface- IndexAccessor
- Parameters:
- context- the evaluation context in which the access is being attempted
- target- the target object upon which the index is being accessed
- index- the index being accessed
- Returns:
- trueif this index accessor is able to write to the index
 
- 
writepublic void write(EvaluationContext context, Object target, Object index, @Nullable Object newValue) Invoke the configured write-method via reflection.Should only be invoked if canWrite(org.springframework.expression.EvaluationContext, java.lang.Object, java.lang.Object)returnstruefor the same arguments.- Specified by:
- writein interface- IndexAccessor
- Parameters:
- context- the evaluation context in which the access is being attempted
- target- the target object upon which the index is being accessed
- index- the index being accessed
- newValue- the new value for the index
 
- 
isCompilablepublic boolean isCompilable()Description copied from interface:CompilableIndexAccessorDetermine if thisIndexAccessoris currently suitable for compilation.May only be known once the index has been read. - Specified by:
- isCompilablein interface- CompilableIndexAccessor
- See Also:
 
- 
getIndexedValueTypeGet the return type of the configured read-method.- Specified by:
- getIndexedValueTypein interface- CompilableIndexAccessor
- See Also:
 
- 
generateCodeDescription copied from interface:CompilableIndexAccessorGenerate bytecode that performs the operation for reading the index.Bytecode should be generated into the supplied MethodVisitorusing context information from theCodeFlowwhere necessary.The supplied indexNodeshould be used to generate the appropriate bytecode to load the index onto the stack. For example, given the expressionbook.authors[0], invokingcodeFlow.generateCodeForArgument(methodVisitor, indexNode, int.class)will ensure that the index (0) is available on the stack as a primitiveint.Will only be invoked if CompilableIndexAccessor.isCompilable()returnstrue.- Specified by:
- generateCodein interface- CompilableIndexAccessor
- Parameters:
- index- the- SpelNodethat represents the index being accessed
- mv- the ASM- MethodVisitorinto which code should be generated
- cf- the current state of the expression compiler
 
 
-