Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite74406a

Browse files
committed
Introduce withAssignmentDisabled() option for SimpleEvaluationContext
To support additional use cases, this commit introduces awithAssignmentDisabled() method in the Builder forSimpleEvaluationContext.Closesgh-33319
1 parentfe4fd00 commite74406a

File tree

2 files changed

+86
-17
lines changed

2 files changed

+86
-17
lines changed

‎spring-expression/src/main/java/org/springframework/expression/spel/support/SimpleEvaluationContext.java‎

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@
6464
* read-only access to properties via {@link DataBindingPropertyAccessor}. Similarly,
6565
* {@link SimpleEvaluationContext#forReadWriteDataBinding()} enables read and write access
6666
* to properties. Alternatively, configure custom accessors via
67-
* {@link SimpleEvaluationContext#forPropertyAccessors} and potentially activate method
68-
* resolution and/or a type converter through the builder.
67+
* {@link SimpleEvaluationContext#forPropertyAccessors}, potentially
68+
* {@linkplain Builder#withAssignmentDisabled() disable assignment}, and optionally
69+
* activate method resolution and/or a type converter through the builder.
6970
*
7071
* <p>Note that {@code SimpleEvaluationContext} is typically not configured
7172
* with a default root object. Instead it is meant to be created once and
@@ -264,9 +265,8 @@ public Object lookupVariable(String name) {
264265
* ({@code ++}), and decrement ({@code --}) operators are disabled.
265266
* @return {@code true} if assignment is enabled; {@code false} otherwise
266267
* @since 5.3.38
267-
* @see #forPropertyAccessors(PropertyAccessor...)
268268
* @see #forReadOnlyDataBinding()
269-
* @see#forReadWriteDataBinding()
269+
* @seeBuilder#withAssignmentDisabled()
270270
*/
271271
@Override
272272
publicbooleanisAssignmentEnabled() {
@@ -275,15 +275,18 @@ public boolean isAssignmentEnabled() {
275275

276276
/**
277277
* Create a {@code SimpleEvaluationContext} for the specified {@link PropertyAccessor}
278-
* delegates: typically a custom {@code PropertyAccessor} specific to a use case
279-
* (e.g. attribute resolution in a custom data structure), potentially combined with
280-
* a {@link DataBindingPropertyAccessor} if property dereferences are needed as well.
281-
* <p>Assignment is enabled within expressions evaluated by the context created via
282-
* this factory method.
278+
* delegates: typically a custom {@code PropertyAccessor} specific to a use case &mdash;
279+
* for example, for attribute resolution in a custom data structure &mdash; potentially
280+
* combined with a {@link DataBindingPropertyAccessor} if property dereferences are
281+
* needed as well.
282+
* <p>By default, assignment is enabled within expressions evaluated by the context
283+
* created via this factory method; however, assignment can be disabled via
284+
* {@link Builder#withAssignmentDisabled()}.
283285
* @param accessors the accessor delegates to use
284286
* @see DataBindingPropertyAccessor#forReadOnlyAccess()
285287
* @see DataBindingPropertyAccessor#forReadWriteAccess()
286288
* @see #isAssignmentEnabled()
289+
* @see Builder#withAssignmentDisabled()
287290
*/
288291
publicstaticBuilderforPropertyAccessors(PropertyAccessor...accessors) {
289292
for (PropertyAccessoraccessor :accessors) {
@@ -292,7 +295,7 @@ public static Builder forPropertyAccessors(PropertyAccessor... accessors) {
292295
"ReflectivePropertyAccessor. Consider using DataBindingPropertyAccessor or a custom subclass.");
293296
}
294297
}
295-
returnnewBuilder(true,accessors);
298+
returnnewBuilder(accessors);
296299
}
297300

298301
/**
@@ -303,22 +306,26 @@ public static Builder forPropertyAccessors(PropertyAccessor... accessors) {
303306
* @see DataBindingPropertyAccessor#forReadOnlyAccess()
304307
* @see #forPropertyAccessors
305308
* @see #isAssignmentEnabled()
309+
* @see Builder#withAssignmentDisabled()
306310
*/
307311
publicstaticBuilderforReadOnlyDataBinding() {
308-
returnnewBuilder(false,DataBindingPropertyAccessor.forReadOnlyAccess());
312+
returnnewBuilder(DataBindingPropertyAccessor.forReadOnlyAccess()).withAssignmentDisabled();
309313
}
310314

311315
/**
312316
* Create a {@code SimpleEvaluationContext} for read-write access to
313317
* public properties via {@link DataBindingPropertyAccessor}.
314-
* <p>Assignment is enabled within expressions evaluated by the context created via
315-
* this factory method.
318+
* <p>By default, assignment is enabled within expressions evaluated by the context
319+
* created via this factory method. Assignment can be disabled via
320+
* {@link Builder#withAssignmentDisabled()}; however, it is preferable to use
321+
* {@link #forReadOnlyDataBinding()} if you desire read-only access.
316322
* @see DataBindingPropertyAccessor#forReadWriteAccess()
317323
* @see #forPropertyAccessors
318324
* @see #isAssignmentEnabled()
325+
* @see Builder#withAssignmentDisabled()
319326
*/
320327
publicstaticBuilderforReadWriteDataBinding() {
321-
returnnewBuilder(true,DataBindingPropertyAccessor.forReadWriteAccess());
328+
returnnewBuilder(DataBindingPropertyAccessor.forReadWriteAccess());
322329
}
323330

324331

@@ -337,13 +344,22 @@ public static final class Builder {
337344
@Nullable
338345
privateTypedValuerootObject;
339346

340-
privatefinalbooleanassignmentEnabled;
347+
privatebooleanassignmentEnabled =true;
341348

342-
privateBuilder(booleanassignmentEnabled,PropertyAccessor...accessors) {
343-
this.assignmentEnabled =assignmentEnabled;
349+
privateBuilder(PropertyAccessor...accessors) {
344350
this.accessors =Arrays.asList(accessors);
345351
}
346352

353+
/**
354+
* Disable assignment within expressions evaluated by this evaluation context.
355+
* @since 5.3.38
356+
* @see SimpleEvaluationContext#isAssignmentEnabled()
357+
*/
358+
publicBuilderwithAssignmentDisabled() {
359+
this.assignmentEnabled =false;
360+
returnthis;
361+
}
362+
347363
/**
348364
* Register the specified {@link MethodResolver} delegates for
349365
* a combination of property access and method resolution.

‎spring-expression/src/test/java/org/springframework/expression/spel/support/SimpleEvaluationContextTests.java‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,59 @@ void forPropertyAccessorsInMixedReadOnlyMode() {
187187
assertIncrementAndDecrementWritesForIndexedStructures(context);
188188
}
189189

190+
@Test
191+
voidforPropertyAccessorsWithAssignmentDisabled() {
192+
SimpleEvaluationContextcontext =SimpleEvaluationContext
193+
.forPropertyAccessors(newCompilableMapAccessor(),DataBindingPropertyAccessor.forReadOnlyAccess())
194+
.withAssignmentDisabled()
195+
.build();
196+
197+
assertCommonReadOnlyModeBehavior(context);
198+
199+
// Map -- with key as property name supported by CompilableMapAccessor
200+
201+
Expressionexpression;
202+
expression =parser.parseExpression("map.yellow");
203+
// setValue() is supported even though assignment is not.
204+
expression.setValue(context,model,"pineapple");
205+
assertThat(expression.getValue(context,model,String.class)).isEqualTo("pineapple");
206+
207+
// WRITE -- via assignment operator
208+
209+
// Variable
210+
assertAssignmentDisabled(context,"#myVar = 'rejected'");
211+
212+
// Property
213+
assertAssignmentDisabled(context,"name = 'rejected'");
214+
assertAssignmentDisabled(context,"map.yellow = 'rejected'");
215+
assertIncrementDisabled(context,"count++");
216+
assertIncrementDisabled(context,"++count");
217+
assertDecrementDisabled(context,"count--");
218+
assertDecrementDisabled(context,"--count");
219+
220+
// Array Index
221+
assertAssignmentDisabled(context,"array[0] = 'rejected'");
222+
assertIncrementDisabled(context,"numbers[0]++");
223+
assertIncrementDisabled(context,"++numbers[0]");
224+
assertDecrementDisabled(context,"numbers[0]--");
225+
assertDecrementDisabled(context,"--numbers[0]");
226+
227+
// List Index
228+
assertAssignmentDisabled(context,"list[0] = 'rejected'");
229+
230+
// Map Index -- key as String
231+
assertAssignmentDisabled(context,"map['red'] = 'rejected'");
232+
233+
// Map Index -- key as pseudo property name
234+
assertAssignmentDisabled(context,"map[yellow] = 'rejected'");
235+
236+
// String Index
237+
assertAssignmentDisabled(context,"name[0] = 'rejected'");
238+
239+
// Object Index
240+
assertAssignmentDisabled(context,"['name'] = 'rejected'");
241+
}
242+
190243

191244
privatevoidassertReadWriteMode(SimpleEvaluationContextcontext) {
192245
// Variables can always be set programmatically within an EvaluationContext.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp