Class ReflectiveIndexAccessor

java.lang.Object
org.springframework.expression.spel.support.ReflectiveIndexAccessor
All Implemented Interfaces:
org.springframework.asm.Opcodes, IndexAccessor, CompilableIndexAccessor, TargetedAccessor

public class ReflectiveIndexAccessor extends Object implements CompilableIndexAccessor
A flexible 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 Summary

    Fields inherited from interface org.springframework.asm.Opcodes

    AALOAD, 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 Summary

    Constructors
    Constructor
    Description
    ReflectiveIndexAccessor(Class<?> targetType, Class<?> indexType, String readMethodName)
    Construct a new ReflectiveIndexAccessor for read-only access.
    ReflectiveIndexAccessor(Class<?> targetType, Class<?> indexType, String readMethodName, @Nullable String writeMethodName)
    Construct a new ReflectiveIndexAccessor for read-write access.
  • Method Summary

    Modifier and Type
    Method
    Description
    boolean
    canRead(EvaluationContext context, Object target, Object index)
    Return true if the supplied target and index can be assigned to the targetType and indexType configured via the constructor.
    boolean
    canWrite(EvaluationContext context, Object target, Object index)
    Return true if a write-method has been configured and canRead(org.springframework.expression.EvaluationContext, java.lang.Object, java.lang.Object) returns true for the same arguments.
    void
    generateCode(SpelNode index, org.springframework.asm.MethodVisitor mv, CodeFlow cf)
    Generate bytecode that performs the operation for reading the index.
    Get the return type of the configured read-method.
    Class<?>[]
    Return an array containing the targetType configured via the constructor.
    boolean
    Determine if this IndexAccessor is currently suitable for compilation.
    read(EvaluationContext context, Object target, Object index)
    Invoke the configured read-method via reflection and return the result wrapped in a TypedValue.
    void
    write(EvaluationContext context, Object target, Object index, @Nullable Object newValue)
    Invoke the configured write-method via reflection.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • ReflectiveIndexAccessor

      public ReflectiveIndexAccessor(Class<?> targetType, Class<?> indexType, String readMethodName)
      Construct a new ReflectiveIndexAccessor for 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
    • ReflectiveIndexAccessor

      public ReflectiveIndexAccessor(Class<?> targetType, Class<?> indexType, String readMethodName, @Nullable String writeMethodName)
      Construct a new ReflectiveIndexAccessor for 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 null if writing is not supported
  • Method Details