Язык выражений Spring

Язык выражений Spring (SpEL) — мощный язык, поддерживающий запросы и динамическую манипуляцию графа объекта. О нём и поговорим.

Синтаксис SpEL напоминает Unified EL, однако предоставляет ряд дополнительных возможностей, к коим относится базовая функциональность строковой шаблонизации и вызов методов. Но несмотря на существование OGNL, MVEL и JBoss EL, SpEL создавался, чтобы Spring-сообщество получило единый и хорошо поддерживаемый язык выражений для всех Spring-продуктов. Что в принципе не мешает по мере необходимости применять другие языки выражений, а также использовать SpEL независимо от продуктов Spring.

Инструменты

Главные классы и интерфейсы применения SpEL находятся в пакете org.springframework.expression и соответствующих подпакетах.

Рассмотрим некоторые интерфейсы. Интерфейс ExpressionParser обеспечивает разбор строки выражения. Например, в нижеуказанном коде строковый литерал выражения помещён в одинарные кавычки. А интерфейс Expression обеспечивает вычисление ранее определённой строки выражения.

Теперь пару слов о методе getValue. Он способен принимать в качестве аргумента класс, к которому будет обеспечено приведение вычисленного значения выражения. Если же приведение будет невозможным, произойдёт выброс исключения EvaluationException.

В большинстве случаев SpEL применяется в целях вычисления выражения в отношении какого-нибудь объекта, для чего существуют 2 способа получения значения из выражения, применение которых зависит от того, станет ли меняться объект между вызовами вычисления выражения. В случае использования StandardEvaluationContext мы предполагаем, что корневой объект не изменится, ведь сборка StandardEvaluationContext при многократном применении — операция относительно дорогостоящая:

Идём далее. Интерфейс EvaluationContext применяется во время вычисления значения выражений из методов, свойств и полей, помогая преобразовывать типы. Spring предоставляет реализацию StandardEvaluationContext, использующую рефлексию в целях манипуляции объекта путём кеширования экземпляров java.lang.reflect.Method/Field/Constructor, что обеспечивает увеличение производительности.

Посредством метода setRootObject() обеспечивается указание корневого объекта, к которому станут применяться выражения, а в методы setVariable() и registerFunction(), соответственно, передаются переменные и функции, которые станут применяться в самом выражении. При регистрации собственных MethodResolver, ConstructorResolver и PropertyAccessor пользователь сможет расширить функционал SpEL для вычисления выражений.

Чтобы настроить возможность разбора выражений, применяют SpelParserConfiguration. При этом объект конфигурации обеспечивает контроль поведения ряда компонентов выражения.

Использование выражений, как правило, подразумевает повышенную гибкость в процессе вычисления значений, но эта гибкость становится возможной в ущерб производительности. Для увеличения производительности применяется компилятор выражений. Компилятор генерирует настоящий Java-класс, что называется, на лету, а его поведение соответствует вычисляемому выражению. Так как само выражение не является типизированным, компилятор берёт во внимание результаты интерпретации и компиляции выражения.

Для примера возьмём выражение someArray[0].someProperty.someOtherProperty < 0.1, предполагающее доступ к элементу массива, числовой операции и разыменованию свойства. Здесь показатели производительности могут значительно различаться. На примере этого выражения можно сказать, что 5 тысяч итераций вычисления без компилятора может составить порядка 75 мс, если же с компилятором — 3 мс.

По дефолту компилятор не включен. Чтобы его включить, есть 2 варианта: — аргументом в конструкторе SpelParserConfiguration; — через системное свойство spring.expression.compiler.mode.

Тут стоит упомянуть три режима компиляции выражений: • OFF — компилятор отключен (этот режим обеспечивается по дефолту); • MEDIATE — компиляция происходит максимально быстро, как правило, после первой интерпретации; • MIXED — в первую очередь выражение вычисляется интерпретатором, однако после некоторого числа вычислений осуществляется переключение на режим компиляции, где выражение компилируется.

Возможности SpEL

На сегодняшний день SpEL поддерживает следующую функциональность:

По материалам сайта https://spring-projects.ru/.