Improve documentation for SpelCompilerMode

Closes gh-33223
This commit is contained in:
Sam Brannen 2024-11-14 11:36:46 +01:00
parent de8a94f30d
commit cca245020d
2 changed files with 64 additions and 22 deletions

View File

@ -444,18 +444,27 @@ component. This section discusses both of these options.
The compiler can operate in one of three modes, which are captured in the The compiler can operate in one of three modes, which are captured in the
`org.springframework.expression.spel.SpelCompilerMode` enum. The modes are as follows. `org.springframework.expression.spel.SpelCompilerMode` enum. The modes are as follows.
* `OFF` (default): The compiler is switched off. `OFF` ::
* `IMMEDIATE`: In immediate mode, the expressions are compiled as soon as possible. This The compiler is switched off, and all expressions will be evaluated in _interpreted_
is typically after the first interpreted evaluation. If the compiled expression fails mode. This is the default mode.
(typically due to a type changing, as described earlier), the caller of the expression `IMMEDIATE` ::
evaluation receives an exception. In immediate mode, expressions are compiled as soon as possible, typically after the
* `MIXED`: In mixed mode, the expressions silently switch between interpreted and first interpreted evaluation. If evaluation of the compiled expression fails (for
compiled mode over time. After some number of interpreted runs, they switch to compiled example, due to a type changing, as described earlier), the caller of the expression
form and, if something goes wrong with the compiled form (such as a type changing, as evaluation receives an exception. If the types of various expression elements change
described earlier), the expression automatically switches back to interpreted form over time, consider switching to `MIXED` mode or turning off the compiler.
again. Sometime later, it may generate another compiled form and switch to it. `MIXED` ::
Basically, the exception that the user gets in `IMMEDIATE` mode is instead handled In mixed mode, expression evaluation silently switches between _interpreted_ and
internally. _compiled_ over time. After some number of successful interpreted runs, the expression
gets compiled. If evaluation of the compiled expression fails (for example, due to a
type changing), that failure will be caught internally, and the system will switch back
to interpreted mode for the given expression. Basically, the exception that the caller
receives in `IMMEDIATE` mode is instead handled internally. Sometime later, the
compiler may generate another compiled form and switch to it. This cycle of switching
between interpreted and compiled mode will continue until the system determines that it
does not make sense to continue trying — for example, when a certain failure threshold
has been reached — at which point the system will permanently switch to interpreted
mode for the given expression.
`IMMEDIATE` mode exists because `MIXED` mode could cause issues for expressions that `IMMEDIATE` mode exists because `MIXED` mode could cause issues for expressions that
have side effects. If a compiled expression blows up after partially succeeding, it have side effects. If a compiled expression blows up after partially succeeding, it

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,30 +17,63 @@
package org.springframework.expression.spel; package org.springframework.expression.spel;
/** /**
* Captures the possible configuration settings for a compiler that can be * Captures the possible configuration settings for a compiler that can be used
* used when evaluating expressions. * when evaluating expressions.
*
* <p>Spring provides a basic compiler for SpEL expressions. Expressions are usually
* interpreted, which provides a lot of dynamic flexibility during evaluation but does
* not provide optimum performance. For occasional expression usage, this is fine, but
* when used by other components such as Spring Integration, performance can be very
* important, and there is no real need for the dynamism.
*
* <p>The SpEL compiler is intended to address this need. During evaluation, the compiler
* generates a Java class that embodies the expression behavior at runtime and uses that
* class to achieve much faster expression evaluation. Due to the lack of typing around
* expressions, the compiler uses information gathered during the interpreted evaluations
* of an expression when performing compilation. For example, SpEL does not know the type
* of a property reference purely from the expression, but during the first interpreted
* evaluation, it finds out what it is. Of course, basing compilation on such derived
* information can cause trouble later if the types of the various expression elements
* change over time. For this reason, compilation is best suited to expressions whose
* type information is not going to change on repeated evaluations.
* *
* @author Andy Clement * @author Andy Clement
* @author Sam Brannen
* @since 4.1 * @since 4.1
*/ */
public enum SpelCompilerMode { public enum SpelCompilerMode {
/** /**
* The compiler is switched off; this is the default. * The compiler is turned off, and all expressions will be evaluated in
* <em>interpreted</em> mode.
* <p>This is the default.
*/ */
OFF, OFF,
/** /**
* In immediate mode, expressions are compiled as soon as possible (usually after 1 interpreted run). * In immediate mode, expressions are compiled as soon as possible, typically
* If a compiled expression fails it will throw an exception to the caller. * after the first interpreted evaluation.
* <p>If evaluation of the compiled expression fails (for example, due to a type
* changing), the caller of the expression evaluation receives an exception.
* <p>If the types of various expression elements change over time, consider
* switching to {@link #MIXED} mode or turning {@linkplain #OFF off} the compiler.
*/ */
IMMEDIATE, IMMEDIATE,
/** /**
* In mixed mode, expression evaluation silently switches between interpreted and compiled over time. * In mixed mode, expression evaluation silently switches between <em>interpreted</em>
* After a number of runs the expression gets compiled. If it later fails (possibly due to inferred * and <em>compiled</em> over time.
* type information changing) then that will be caught internally and the system switches back to * <p>After some number of successful interpreted runs, the expression gets
* interpreted mode. It may subsequently compile it again later. * compiled. If evaluation of the compiled expression fails (for example, due
* to a type changing), that failure will be caught internally, and the system
* will switch back to interpreted mode for the given expression. Basically,
* the exception that the caller receives in {@link #IMMEDIATE} mode is instead
* handled internally. Sometime later, the compiler may generate another compiled form and switch to it.
* This cycle of switching between interpreted and compiled mode will continue
* until the system determines that it does not make sense to continue trying
* &mdash; for example, when a certain failure threshold has been reached &mdash;
* at which point the system will permanently switch to interpreted mode for the
* given expression.
*/ */
MIXED MIXED