diff --git a/framework-docs/modules/ROOT/pages/core/expressions/evaluation.adoc b/framework-docs/modules/ROOT/pages/core/expressions/evaluation.adoc index e724a393e46..bf253821b4e 100644 --- a/framework-docs/modules/ROOT/pages/core/expressions/evaluation.adoc +++ b/framework-docs/modules/ROOT/pages/core/expressions/evaluation.adoc @@ -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 `org.springframework.expression.spel.SpelCompilerMode` enum. The modes are as follows. -* `OFF` (default): The compiler is switched off. -* `IMMEDIATE`: In immediate mode, the expressions are compiled as soon as possible. This - is typically after the first interpreted evaluation. If the compiled expression fails - (typically due to a type changing, as described earlier), the caller of the expression - evaluation receives an exception. -* `MIXED`: In mixed mode, the expressions silently switch between interpreted and - compiled mode over time. After some number of interpreted runs, they switch to compiled - form and, if something goes wrong with the compiled form (such as a type changing, as - described earlier), the expression automatically switches back to interpreted form - again. Sometime later, it may generate another compiled form and switch to it. - Basically, the exception that the user gets in `IMMEDIATE` mode is instead handled - internally. +`OFF` :: + The compiler is switched off, and all expressions will be evaluated in _interpreted_ + mode. This is the default mode. +`IMMEDIATE` :: + In immediate mode, expressions are compiled as soon as possible, typically after the + first interpreted evaluation. If evaluation of the compiled expression fails (for + example, due to a type changing, as described earlier), the caller of the expression + evaluation receives an exception. If the types of various expression elements change + over time, consider switching to `MIXED` mode or turning off the compiler. +`MIXED` :: + In mixed mode, expression evaluation silently switches between _interpreted_ and + _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 have side effects. If a compiled expression blows up after partially succeeding, it diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/SpelCompilerMode.java b/spring-expression/src/main/java/org/springframework/expression/spel/SpelCompilerMode.java index cf6e024c9aa..fdf1bef11da 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/SpelCompilerMode.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/SpelCompilerMode.java @@ -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"); * you may not use this file except in compliance with the License. @@ -17,30 +17,63 @@ package org.springframework.expression.spel; /** - * Captures the possible configuration settings for a compiler that can be - * used when evaluating expressions. + * Captures the possible configuration settings for a compiler that can be used + * when evaluating expressions. + * + *

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. + * + *

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 Sam Brannen * @since 4.1 */ public enum SpelCompilerMode { /** - * The compiler is switched off; this is the default. + * The compiler is turned off, and all expressions will be evaluated in + * interpreted mode. + *

This is the default. */ OFF, /** - * In immediate mode, expressions are compiled as soon as possible (usually after 1 interpreted run). - * If a compiled expression fails it will throw an exception to the caller. + * In immediate mode, expressions are compiled as soon as possible, typically + * after the first interpreted evaluation. + *

If evaluation of the compiled expression fails (for example, due to a type + * changing), the caller of the expression evaluation receives an exception. + *

If the types of various expression elements change over time, consider + * switching to {@link #MIXED} mode or turning {@linkplain #OFF off} the compiler. */ IMMEDIATE, /** - * In mixed mode, expression evaluation silently switches between interpreted and compiled over time. - * After a number of runs the expression gets compiled. If it later fails (possibly due to inferred - * type information changing) then that will be caught internally and the system switches back to - * interpreted mode. It may subsequently compile it again later. + * In mixed mode, expression evaluation silently switches between interpreted + * and 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 {@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 + * — 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. */ MIXED