on
SpEL (스프링 Expression Language)
스프링 프레임워크 핵심기술을 공부하고 정리하는 포스트입니다.
SpEL(Spring Expression Language)
SpEL은 Spring Expression Language의 줄임말로 여기서 Expression Language, 줄여서 EL은 객체 그래프를 조회하거나 조작하는 기능을 제공한다. 예시로 JSP에서 EL을 볼 수 있다.
스프링에서는 EL의 기능과 비슷하지만, 메소드 호출을 지원하고 문자열 템플릿 기능도 제공해주는 EL이 프로젝트 전반에 걸쳐서 필요했다. 이러한 필요에 의해서 만들어진 것이 바로 SpEL이며 스프링 코어단에 추가 되었다.
SpEL은 스프링 3.0부터 지원하는데 스프링 코어단에 추가되었다고 코어단에서만 사용되는 것이 아니라, 시큐리티, 데이터 등등 프로젝트 전체에 사용된다.
AppRunner를 만들고 SpEL이 어떻게 생겼는지 보도록하자.
참고로 ApplicationRunner라는 인터페이스를 구현하면 SpringBoot Application이 실행된 후에 AppRunner 안에 있는 코드들이 바로 실행이 된다.
▶ @Value 애노테이션
SpEL이 사용되는 곳 중에 하나는 @Value 애노테이션이다. @Value 애노테이션을 선언한 후에 표현식이나 프로퍼티를 사용할 수 있다.
package me.gracenam.demospring51;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class AppRunner implements ApplicationRunner {
@Value("#{1 + 1}")
int value;
@Value("#{'hello ' + 'world'}")
String greeting;
@Value("#{1 eq 1}")
boolean trueOrFalse;
@Value("hello")
String hello;
@Value("${my.value}")
int myValue;
@Value("#{${my.value} eq 100}")
boolean isMyValue100;
@Value("#{'spring'}")
String spring;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("===========================");
System.out.println(value);
System.out.println(greeting);
System.out.println(trueOrFalse);
System.out.println(hello);
System.out.println(myValue);
System.out.println(isMyValue100);
System.out.println(spring);
}
}
my.value = 100
코드에서 @Value 애노테이션 뒤에 붙은 #{ }
은 표현식을 사용하고, ${ }
는 프로퍼티를 사용한다. ${my.value}
는 application.properties라는 프로퍼티에 등록된 값을 읽어오는 것이다. 그리고 #{${my.value} eq 100}
은 표현식 내부에 프로퍼티를 사용한 것인데 이처럼 표현식 안에 프로퍼티를 가질 수는 있지만 프로퍼티 안에 표현식을 사용하는 것은 허용되지 않는다.
#{'spring'}
은 리터럴을 표현한 것인데 표현식 내에 문자열을 입력하면 그 문자열이 리터럴 그대로 전달되는 것이다. 그 외에도 Arrays, List, Maps, Indexers 등이 지원된다. 더 자세한 것은 Reference를 참고하자.
▶ Bean 참고
다른 방법은 Bean을 참고하는 것이다. Sample이라는 Bean을 만들어서 data = 200
이라는 정보를 입력했다.
package me.gracenam.demospring51;
import org.springframework.stereotype.Component;
@Component
public class Sample {
private int data = 200;
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
}
package me.gracenam.demospring51;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class AppRunner implements ApplicationRunner {
@Value("#{sample.data}")
int sampleDate;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("===========================");
System.out.println(sampleDate);
}
}
이처럼 빈에 있는 값을 가져와서 출력할 수 있다.
SpEL을 지원하는 기능들이 더 있는데
- @ConditionalOnExpression 애노테이션
- @ConditionalOn 애노테이션은 선택적으로 빈을 등록하거나 빈 설정 파일을 읽어들일 때 사용하는 애노테이션인데, 이 경우에 Expression 기반으로 빈을 선별할 수 있다.
- 스프링 시큐리티
- 메소드 시큐리티, @PreAuthorize, @PostAuthorize, @PreFilter, @PostFilter
- 시큐리티에서 사용되는 함수들은 EvaluationContext1에서 오는 것이다. EvaluationContext로 Bean을 만들어주면 빈이 제공하는 함수들을 쓸 수 있다.
- 스프링 데이터
- 스프링 데이터의 @Query 애노테이션 같은 경우에도 메서드에서 받은 파라미터 인자에 들어있는 필드 값을 참조하거나 인덱스 기반으로 참조해서 사용할 수 있다.
- Thymeleaf
- 스프링 프로젝트 뿐만 아니라 Thymeleaf라는 뷰 템플릿 엔진에서도 SpEL을 지원한다.
등이 있다.
마지막으로 SpEL의 기반을 이해하기 위한 두 클래스 중 ExpressionParser의 예제를 살펴보자.
package me.gracenam.demospring51;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Component;
@Component
public class AppRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("2 + 100");
Integer value = expression.getValue(Integer.class);
System.out.println("====================");
System.out.println(value);
}
}
필요에 따라서 ExpressionParser를 직접 작성해서 사용할 수 있다. parser.parseExpression()
의 경우 이미 자체가 Expression이기 때문에 괄호 안에 들어갈 값만 입력해주면 된다. 이렇게 한 후 출력을 해보면 값이 나오는 것을 볼 수 있다.
Reference
-
StandardEvaluationContext context = new StandardEvaluationContext(bean) ↩
Comments
SPRING 의 다른 글
-
스프링 타입 컨터버 24 Jun 2022
-
API 예외 처리 17 Jun 2022
-
예외 처리와 오류 페이지 12 Jun 2022
-
로그인 처리 - 인터셉터 08 Jun 2022
-
로그인 처리 - 필터 06 Jun 2022
-
로그인 처리 - 쿠키, 세션 31 May 2022
-
Bean Validation 22 May 2022
-
검증 22 May 2022
-
메시지, 국제화 21 May 2022
-
타임리프 - 스프링 통합과 폼 19 May 2022
-
타임리프 - 기본 기능 10 May 2022
-
스프링 MVC 기본 기능 - 웹 페이지 만들기 02 May 2022
-
스프링 MVC 기본 기능 - HTTP 응답 30 Apr 2022
-
스프링 MVC 기본 기능 - HTTP 요청 24 Apr 2022
-
스프링 MVC 기본 기능 - 요청 매핑 19 Apr 2022
-
스프링 MVC 기본 기능 19 Apr 2022
-
스프링 MVC 구조 이해 14 Apr 2022
-
MVC 프레임워크 만들기 - V4, V5 12 Apr 2022
-
MVC 프레임워크 만들기 - V1, V2, V3 09 Apr 2022
-
서블릿, JSP, MVC 패턴 05 Apr 2022
-
서블릿 29 Mar 2022
-
웹 애플리케이션 이해 24 Mar 2022
-
스프링 웹 계층이란? 05 Nov 2021
-
스프링 시큐리티 공식문서 번역 27 Sep 2021
-
스프링 AOP 총정리 : 개념, 프록시 기반 AOP, @AOP 27 Apr 2021
-
SpEL (스프링 Expression Language) 25 Apr 2021
-
데이터 바인딩 추상화 : Converter와 Formatter 21 Apr 2021
-
데이터 바인딩 추상화 : PropertyEditor 12 Apr 2021
-
Validation 추상화 10 Apr 2021
-
Resource 추상화 08 Apr 2021
-
IoC 컨테이너 9부 07 Apr 2021
-
IoC 컨테이너 8부 06 Apr 2021
-
IoC 컨테이너 7부 02 Apr 2021
-
IoC 컨테이너 6부 29 Mar 2021
-
IoC 컨테이너 5부 27 Mar 2021
-
IoC 컨테이너 4부 23 Mar 2021
-
IoC 컨테이너 3부 20 Mar 2021
-
IoC 컨테이너 2부 18 Mar 2021
-
IoC 컨테이너 1부 12 Mar 2021
-
스프링 PSA 07 Jan 2021
-
스프링 @AOP 실습 07 Jan 2021
-
프록시 패턴 06 Jan 2021
-
스프링 AOP 04 Jan 2021
-
의존성 주입(Dependency Injection) 04 Jan 2021
-
스프링 빈(Bean) 02 Jan 2021
-
스프링 IoC 컨테이너 01 Jan 2021
-
스프링 IoC 01 Jan 2021