0 added
0 removed
Original
2026-01-01
Modified
2026-03-10
1
<p>Язык выражений Spring (<strong>SpEL</strong>) - мощный язык, поддерживающий запросы и динамическую манипуляцию графа объекта. О нём и поговорим.</p>
1
<p>Язык выражений Spring (<strong>SpEL</strong>) - мощный язык, поддерживающий запросы и динамическую манипуляцию графа объекта. О нём и поговорим.</p>
2
<p>Синтаксис SpEL напоминает Unified EL, однако предоставляет ряд дополнительных возможностей, к коим относится базовая функциональность строковой шаблонизации и вызов методов. Но несмотря на существование OGNL, MVEL и JBoss EL, SpEL создавался, чтобы Spring-сообщество получило<strong>единый и хорошо поддерживаемый язык выражений для всех Spring-продуктов</strong>. Что в принципе не мешает по мере необходимости применять другие языки выражений, а также использовать SpEL независимо от продуктов Spring.</p>
2
<p>Синтаксис SpEL напоминает Unified EL, однако предоставляет ряд дополнительных возможностей, к коим относится базовая функциональность строковой шаблонизации и вызов методов. Но несмотря на существование OGNL, MVEL и JBoss EL, SpEL создавался, чтобы Spring-сообщество получило<strong>единый и хорошо поддерживаемый язык выражений для всех Spring-продуктов</strong>. Что в принципе не мешает по мере необходимости применять другие языки выражений, а также использовать SpEL независимо от продуктов Spring.</p>
3
<h2>Инструменты</h2>
3
<h2>Инструменты</h2>
4
<p>Главные классы и интерфейсы применения SpEL находятся в пакете org.springframework.expression и соответствующих подпакетах.</p>
4
<p>Главные классы и интерфейсы применения SpEL находятся в пакете org.springframework.expression и соответствующих подпакетах.</p>
5
<p>Рассмотрим некоторые интерфейсы. Интерфейс<strong>ExpressionParser</strong>обеспечивает разбор строки выражения. Например, в нижеуказанном коде строковый литерал выражения помещён в одинарные кавычки. А интерфейс<strong>Expression</strong>обеспечивает вычисление ранее определённой строки выражения.</p>
5
<p>Рассмотрим некоторые интерфейсы. Интерфейс<strong>ExpressionParser</strong>обеспечивает разбор строки выражения. Например, в нижеуказанном коде строковый литерал выражения помещён в одинарные кавычки. А интерфейс<strong>Expression</strong>обеспечивает вычисление ранее определённой строки выражения.</p>
6
<p>Теперь пару слов о методе<strong>getValue</strong>. Он способен принимать в качестве аргумента класс, к которому будет обеспечено приведение вычисленного значения выражения. Если же приведение будет невозможным, произойдёт выброс исключения<strong>EvaluationException</strong>.</p>
6
<p>Теперь пару слов о методе<strong>getValue</strong>. Он способен принимать в качестве аргумента класс, к которому будет обеспечено приведение вычисленного значения выражения. Если же приведение будет невозможным, произойдёт выброс исключения<strong>EvaluationException</strong>.</p>
7
<p>В большинстве случаев SpEL применяется в целях вычисления выражения в отношении какого-нибудь объекта, для чего существуют 2 способа получения значения из выражения, применение которых зависит от того, станет ли меняться объект между вызовами вычисления выражения. В случае использования<strong>StandardEvaluationContext</strong>мы предполагаем, что корневой объект не изменится, ведь сборка<strong>StandardEvaluationContext</strong>при многократном применении - операция относительно дорогостоящая:</p>
7
<p>В большинстве случаев SpEL применяется в целях вычисления выражения в отношении какого-нибудь объекта, для чего существуют 2 способа получения значения из выражения, применение которых зависит от того, станет ли меняться объект между вызовами вычисления выражения. В случае использования<strong>StandardEvaluationContext</strong>мы предполагаем, что корневой объект не изменится, ведь сборка<strong>StandardEvaluationContext</strong>при многократном применении - операция относительно дорогостоящая:</p>
8
<p>Идём далее. Интерфейс<strong>EvaluationContext</strong>применяется во время вычисления значения выражений из методов, свойств и полей, помогая преобразовывать типы. Spring предоставляет реализацию<strong>StandardEvaluationContext</strong>, использующую рефлексию в целях манипуляции объекта путём кеширования экземпляров<strong>java.lang.reflect.Method/Field/Constructor</strong>, что обеспечивает увеличение производительности.</p>
8
<p>Идём далее. Интерфейс<strong>EvaluationContext</strong>применяется во время вычисления значения выражений из методов, свойств и полей, помогая преобразовывать типы. Spring предоставляет реализацию<strong>StandardEvaluationContext</strong>, использующую рефлексию в целях манипуляции объекта путём кеширования экземпляров<strong>java.lang.reflect.Method/Field/Constructor</strong>, что обеспечивает увеличение производительности.</p>
9
<p>Посредством метода setRootObject() обеспечивается указание корневого объекта, к которому станут применяться выражения, а в методы setVariable() и registerFunction(), соответственно, передаются переменные и функции, которые станут применяться в самом выражении. При регистрации собственных<strong>MethodResolver, ConstructorResolver и PropertyAccessor</strong>пользователь сможет расширить функционал SpEL для вычисления выражений.</p>
9
<p>Посредством метода setRootObject() обеспечивается указание корневого объекта, к которому станут применяться выражения, а в методы setVariable() и registerFunction(), соответственно, передаются переменные и функции, которые станут применяться в самом выражении. При регистрации собственных<strong>MethodResolver, ConstructorResolver и PropertyAccessor</strong>пользователь сможет расширить функционал SpEL для вычисления выражений.</p>
10
<p>Чтобы настроить возможность разбора выражений, применяют<strong>SpelParserConfiguration</strong>. При этом объект конфигурации обеспечивает контроль поведения ряда компонентов выражения.</p>
10
<p>Чтобы настроить возможность разбора выражений, применяют<strong>SpelParserConfiguration</strong>. При этом объект конфигурации обеспечивает контроль поведения ряда компонентов выражения.</p>
11
<p>Использование выражений, как правило, подразумевает повышенную гибкость в процессе вычисления значений, но эта гибкость становится возможной в ущерб производительности. Для увеличения производительности применяется<strong>компилятор выражений</strong>. Компилятор генерирует настоящий Java-класс, что называется, на лету, а его поведение соответствует вычисляемому выражению. Так как само выражение не является типизированным, компилятор берёт во внимание результаты интерпретации и компиляции выражения.</p>
11
<p>Использование выражений, как правило, подразумевает повышенную гибкость в процессе вычисления значений, но эта гибкость становится возможной в ущерб производительности. Для увеличения производительности применяется<strong>компилятор выражений</strong>. Компилятор генерирует настоящий Java-класс, что называется, на лету, а его поведение соответствует вычисляемому выражению. Так как само выражение не является типизированным, компилятор берёт во внимание результаты интерпретации и компиляции выражения.</p>
12
<p>Для примера возьмём выражение someArray[0].someProperty.someOtherProperty < 0.1, предполагающее доступ к элементу массива, числовой операции и разыменованию свойства. Здесь показатели производительности могут значительно различаться. На примере этого выражения можно сказать, что 5 тысяч итераций вычисления без компилятора может составить порядка 75 мс, если же с компилятором - 3 мс.</p>
12
<p>Для примера возьмём выражение someArray[0].someProperty.someOtherProperty < 0.1, предполагающее доступ к элементу массива, числовой операции и разыменованию свойства. Здесь показатели производительности могут значительно различаться. На примере этого выражения можно сказать, что 5 тысяч итераций вычисления без компилятора может составить порядка 75 мс, если же с компилятором - 3 мс.</p>
13
<p>По дефолту компилятор не включен. Чтобы его включить, есть 2 варианта: - аргументом в конструкторе<strong>SpelParserConfiguration</strong>; - через системное свойство<strong>spring.expression.compiler.mode</strong>.</p>
13
<p>По дефолту компилятор не включен. Чтобы его включить, есть 2 варианта: - аргументом в конструкторе<strong>SpelParserConfiguration</strong>; - через системное свойство<strong>spring.expression.compiler.mode</strong>.</p>
14
<p>Тут стоит упомянуть три режима компиляции выражений: •<strong>OFF</strong>- компилятор отключен (этот режим обеспечивается по дефолту); •<strong>MEDIATE</strong>- компиляция происходит максимально быстро, как правило, после первой интерпретации; •<strong>MIXED</strong>- в первую очередь выражение вычисляется интерпретатором, однако после некоторого числа вычислений осуществляется переключение на режим компиляции, где выражение компилируется.</p>
14
<p>Тут стоит упомянуть три режима компиляции выражений: •<strong>OFF</strong>- компилятор отключен (этот режим обеспечивается по дефолту); •<strong>MEDIATE</strong>- компиляция происходит максимально быстро, как правило, после первой интерпретации; •<strong>MIXED</strong>- в первую очередь выражение вычисляется интерпретатором, однако после некоторого числа вычислений осуществляется переключение на режим компиляции, где выражение компилируется.</p>
15
<h2>Возможности SpEL</h2>
15
<h2>Возможности SpEL</h2>
16
<p>На сегодняшний день SpEL поддерживает следующую функциональность:</p>
16
<p>На сегодняшний день SpEL поддерживает следующую функциональность:</p>
17
<p><em>По материалам сайта https://spring-projects.ru/.</em></p>
17
<p><em>По материалам сайта https://spring-projects.ru/.</em></p>
18
18