Top Description Inners Fields Constructors Methods
org.springframework.expression.spel.standard

public final Class SpelCompiler

extends Object
implements Opcodes
Class Inheritance
All Implemented Interfaces
org.springframework.asm.Opcodes
Imports
java.net.URL, .URLClassLoader, java.util.Map, java.util.concurrent.atomic.AtomicInteger, org.apache.commons.logging.Log, .LogFactory, org.springframework.asm.ClassWriter, .MethodVisitor, .Opcodes, org.springframework.expression.Expression, org.springframework.expression.spel.CodeFlow, .CompiledExpression, .SpelParserConfiguration, org.springframework.expression.spel.ast.SpelNodeImpl, org.springframework.lang.Nullable, org.springframework.util.ClassUtils, .ConcurrentReferenceHashMap, .ReflectionUtils, .StringUtils

A SpelCompiler will take a regular parsed expression and create (and load) a class containing byte code that does the same thing as that expression. The compiled form of an expression will evaluate far faster than the interpreted form.

The SpelCompiler is not currently handling all expression types but covers many of the common cases. The framework is extensible to cover more cases in the future. For absolute maximum speed there is *no checking* in the compiled code. The compiled version of the expression uses information learned during interpreted runs of the expression when it generates the byte code. For example if it knows that a particular property dereference always seems to return a Map then it will generate byte code that expects the result of the property dereference to be a Map. This ensures maximal performance but should the dereference result in something other than a map, the compiled expression will fail - like a ClassCastException would occur if passing data of an unexpected type in a regular Java program.

Due to the lack of checking there are likely some expressions that should never be compiled, for example if an expression is continuously dealing with different types of data. Due to these cases the compiler is something that must be selectively turned on for an associated SpelExpressionParser (through the SpelParserConfiguration object), it is not on by default.

Individual expressions can be compiled by calling SpelCompiler.compile(expression).

Authors
Andy Clement, Juergen Hoeller
Since
4.1

Nested and Inner Type Summary

Modifier and TypeClass and Description
private static class
SpelCompiler.ChildClassLoader

A ChildClassLoader will load the generated compiled expression classes.

private class
SpelCompiler.ExpressionClassWriter

An ASM ClassWriter extension bound to the SpelCompiler's ClassLoader.

Field Summary

Modifier and TypeField and Description
private volatile SpelCompiler.ChildClassLoader
private static final int
private static final Map<ClassLoader, SpelCompiler>
private static final Log
private final AtomicInteger

Constructor Summary

AccessConstructor and Description
private

Method Summary

Modifier and TypeMethod and Description
public CompiledExpression

Returns:

an instance of the class implementing the compiled expression, or null if compilation is not possible
compile
(SpelNodeImpl
the expression to compile
expression
)

Attempt compilation of the supplied expression.

public static boolean

Returns:

true if the expression was successfully compiled, false otherwise
compile
(Expression
the expression to compile
expression
)

Request that an attempt is made to compile the specified expression.

private Class<? extends CompiledExpression>

Returns:

the expression call, or null if the decision was to opt out of compilation during code generation
createExpressionClass
(SpelNodeImpl
the expression to be compiled
expressionToCompile
)

Generate the class that encapsulates the compiled expression and define it.

public static SpelCompiler

Returns:

a corresponding SpelCompiler instance
getCompiler
(ClassLoader
the ClassLoader to use as the basis for compilation
classLoader
)

Factory method for compiler instances.

private int
private Class<? extends CompiledExpression>

Returns:

the Class object for the compiled expression
loadClass
(String
the name of the class
name
,
byte[]
the bytecode for the class
bytes
)

Load a compiled expression class.

public static void
revertToInterpreted(Expression
the expression
expression
)

Request to revert to the interpreter for expression evaluation.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

childClassLoaderback to summary
private volatile SpelCompiler.ChildClassLoader childClassLoader
CLASSES_DEFINED_LIMITback to summary
private static final int CLASSES_DEFINED_LIMIT
compilersback to summary
private static final Map<ClassLoader, SpelCompiler> compilers
loggerback to summary
private static final Log logger
suffixIdback to summary
private final AtomicInteger suffixId

Constructor Detail

SpelCompilerback to summary
private SpelCompiler(ClassLoader classloader)

Method Detail

compileback to summary
public CompiledExpression compile(SpelNodeImpl expression)

Attempt compilation of the supplied expression. A check is made to see if it is compilable before compilation proceeds. The check involves visiting all the nodes in the expression AST and ensuring enough state is known about them that bytecode can be generated for them.

Parameters
expression:SpelNodeImpl

the expression to compile

Returns:CompiledExpression

an instance of the class implementing the compiled expression, or null if compilation is not possible

Annotations
@Nullable
compileback to summary
public static boolean compile(Expression expression)

Request that an attempt is made to compile the specified expression. It may fail if components of the expression are not suitable for compilation or the data types involved are not suitable for compilation. Used for testing.

Parameters
expression:Expression

the expression to compile

Returns:boolean

true if the expression was successfully compiled, false otherwise

createExpressionClassback to summary
private Class<? extends CompiledExpression> createExpressionClass(SpelNodeImpl expressionToCompile)

Generate the class that encapsulates the compiled expression and define it. The generated class will be a subtype of CompiledExpression.

Parameters
expressionToCompile:SpelNodeImpl

the expression to be compiled

Returns:Class<? extends CompiledExpression>

the expression call, or null if the decision was to opt out of compilation during code generation

Annotations
@Nullable
getCompilerback to summary
public static SpelCompiler getCompiler(ClassLoader classLoader)

Factory method for compiler instances. The returned SpelCompiler will attach a class loader as the child of the given class loader and this child will be used to load compiled expressions.

Parameters
classLoader:ClassLoader

the ClassLoader to use as the basis for compilation

Returns:SpelCompiler

a corresponding SpelCompiler instance

getNextSuffixback to summary
private int getNextSuffix()
loadClassback to summary
private Class<? extends CompiledExpression> loadClass(String name, byte[] bytes)

Load a compiled expression class. Makes sure the classloaders aren't used too much because they anchor compiled classes in memory and prevent GC. If you have expressions continually recompiling over time then by replacing the classloader periodically at least some of the older variants can be garbage collected.

Parameters
name:String

the name of the class

bytes:byte[]

the bytecode for the class

Returns:Class<? extends CompiledExpression>

the Class object for the compiled expression

Annotations
@SuppressWarnings:unchecked
revertToInterpretedback to summary
public static void revertToInterpreted(Expression expression)

Request to revert to the interpreter for expression evaluation. Any compiled form is discarded but can be recreated by later recompiling again.

Parameters
expression:Expression

the expression

org.springframework.expression.spel.standard back to summary

private Class SpelCompiler.ChildClassLoader

extends URLClassLoader
Class Inheritance

A ChildClassLoader will load the generated compiled expression classes.

Field Summary

Modifier and TypeField and Description
private final AtomicInteger
private static final URL[]

Constructor Summary

AccessConstructor and Description
public

Method Summary

Modifier and TypeMethod and Description
public Class<?>
defineClass(String name, byte[] bytes)

public int
Inherited from java.net.URLClassLoader:
addURLclosedefinePackagefindClassfindResourcefindResourcesgetPermissionsgetResourceAsStreamgetURLsnewInstancenewInstance

Field Detail

classesDefinedCountback to summary
private final AtomicInteger classesDefinedCount
NO_URLSback to summary
private static final URL[] NO_URLS

Constructor Detail

ChildClassLoaderback to summary
public ChildClassLoader(ClassLoader classLoader)

Method Detail

defineClassback to summary
public Class<?> defineClass(String name, byte[] bytes)
getClassesDefinedCountback to summary
public int getClassesDefinedCount()
org.springframework.expression.spel.standard back to summary

private Class SpelCompiler.ExpressionClassWriter

extends ClassWriter
Class Inheritance

An ASM ClassWriter extension bound to the SpelCompiler's ClassLoader.

Field Summary

Inherited from org.springframework.asm.ClassWriter:
COMPUTE_FRAMESCOMPUTE_MAXS

Constructor Summary

AccessConstructor and Description
public

Method Summary

Modifier and TypeMethod and Description
protected ClassLoader
getClassLoader()

Overrides org.springframework.asm.ClassWriter.getClassLoader.

Returns the ClassLoader to be used by the default implementation of getCommonSuperClass(String, String), that of this ClassWriter's runtime type by default.
Inherited from org.springframework.asm.ClassWriter:
getCommonSuperClasshasFlagsnewClassnewConstnewConstantDynamicnewFieldnewHandlenewHandlenewInvokeDynamicnewMethodnewMethodTypenewModulenewNameTypenewPackagenewUTF8toByteArrayvisitvisitAnnotationvisitAttributevisitEndvisitFieldvisitInnerClassvisitMethodvisitModulevisitNestHostvisitNestMembervisitOuterClassvisitPermittedSubclassvisitRecordComponentvisitSourcevisitTypeAnnotation

Constructor Detail

ExpressionClassWriterback to summary
public ExpressionClassWriter()

Method Detail

getClassLoaderback to summary
protected ClassLoader getClassLoader()

Overrides org.springframework.asm.ClassWriter.getClassLoader.

Doc from org.springframework.asm.ClassWriter.getClassLoader.

Returns the ClassLoader to be used by the default implementation of getCommonSuperClass(String, String), that of this ClassWriter's runtime type by default.

Returns:ClassLoader

ClassLoader

Annotations
@Override