Spring Expression Language (SpEL)
SpEL은 Spring 프레임워크에서 제공하는 강력한 표현식 언어. 런타임에 객체 그래프를 조회하고 조작하는 기능을 제공. XML 설정 파일, 어노테이션, Java 코드 등 다양한 곳에서 사용할 수 있다.
주요 기능
- 객체 그래프 탐색: 객체의 속성, 메서드 호출, 배열/리스트/맵 요소 접근 등을 지원.
- 연산: 산술 연산, 관계 연산, 논리 연산, 정규식 매칭 등을 수행.
- 메서드 호출: 객체의 메서드를 호출하고 결과를 반환받을 수 있다.
- 생성자 호출: 새로운 객체를 생성할 수 있다.
- 변수 및 함수 정의: 표현식 내에서 변수를 정의하고 사용하거나, 사용자 정의 함수를 등록하여 호출할 수 있다.
- 컬렉션 처리: 컬렉션(리스트, 맵 등)에 대한 프로젝션, 선택, 필터링 등을 수행할 수 있다.
- Ternary Operator (삼항 연산자): 조건에 따라 값을 선택하는 삼항 연산자를 지원 (condition ? valueIfTrue : valueIfFalse).
- Elvis Operator: null-safe한 방식으로 값을 할당하는 Elvis 연산자를 지원 (value ?: defaultValue).
- Safe Navigation Operator: null-safe한 방식으로 객체 그래프를 탐색하는 Safe Navigation 연산자를 지원 (object?.property).
사용 예시
1. XML 설정 파일에서
XML
<bean id="myBean" class="com.example.MyBean">
<property name="javaHome" value="#{systemProperties['java.home']}"/>
<property name="userName" value="#{userBean.name}"/>
<property name="formattedName" value="#{userBean.formatName('Mr.')}"/>
<property name="agePlusTen" value="#{userBean.age + 10}"/>
<property name="greeting" value="#{'Hello, ' + userBean.name}"/>
<property name="isAdult" value="#{userBean.age >= 18 and userBean.isMember()}"/>
<property name="displayName" value="#{userBean.nickname != null ? userBean.nickname : userBean.name}"/>
<property name="description" value="#{userBean.description ?: 'No description available'}"/>
<property name="addressCity" value="#{userBean.address?.city}"/>
</bean>
2. 어노테이션에서
Java
@Component
public class MyComponent {
@Value("#{systemProperties['java.version']}") // 시스템 프로퍼티
private String javaVersion;
@Value("#{myService.calculate(10, 20)}") // 메서드 호출
private int calculationResult;
@Value("#{myBean.name?.toUpperCase()}") // Safe Navigation + 메서드
private String upperCaseName;
@Value("#{user.age > 18 ? 'Adult' : 'Minor'}")
private String ageCategory;
@Value("#{user.email ?: 'anonymous@example.com'}") // Elvis 연산자
private String email;
}
3. Java 코드에서 (SpelExpressionParser 사용)
Java
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class SpelExample {
public static void main(String[] args) {
ExpressionParser parser = new SpelExpressionParser();
// 문자열 표현식
Expression exp1 = parser.parseExpression("'Hello, SpEL!'");
String message = (String) exp1.getValue(); // "Hello, SpEL!"
System.out.println(message);
// 객체 속성 접근
User user = new User("Alice", 30);
EvaluationContext context = new StandardEvaluationContext(user);
Expression exp2 = parser.parseExpression("name");
String name = (String) exp2.getValue(context); // "Alice"
System.out.println(name);
// 메서드 호출
Expression exp3 = parser.parseExpression("name.toUpperCase()");
String upperCaseName = (String) exp3.getValue(context); // "ALICE"
System.out.println(upperCaseName);
// 연산
Expression exp4 = parser.parseExpression("age + 5");
Integer agePlusFive = (Integer) exp4.getValue(context); // 35
System.out.println(agePlusFive);
// 리스트
Expression exp5 = parser.parseExpression("{1, 2, 3, 4}");
List<Integer> numbers = (List<Integer>) exp5.getValue(); // [1, 2, 3, 4]
System.out.println(numbers);
// 맵
Expression exp6 = parser.parseExpression("{name:'John', age:25}");
Map<String, Object> map = (Map<String, Object>)exp6.getValue(); // {name=John, age=25}
System.out.println(map);
// T(클래스) 표현식 (static 메서드, static 필드, 생성자 호출)
Expression exp7 = parser.parseExpression("T(java.lang.Math).random()");
Double randomNumber = (Double) exp7.getValue();
System.out.println(randomNumber);
// 생성자 호출
Expression exp8 = parser.parseExpression("new java.util.Date()");
java.util.Date date = (java.util.Date) exp8.getValue();
System.out.println(date);
}
}
class User {
public String name;
public int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName(){ return name; }
public int getAge() { return age; }
}
주요 연산자 및 표현식
리터럴 | 'string', 123, 3.14, true, false, null | 문자열, 정수, 실수, 불린, null 값을 나타냄. |
속성 접근 | object.property | 객체의 속성 값을 가져온다. |
메서드 호출 | object.method(arg1, arg2, ...) | 객체의 메서드를 호출. |
배열/리스트/맵 접근 | array[index], list[index], map[key] | 배열, 리스트, 맵의 요소에 접근. |
산술 연산 | +, -, *, /, %, ^ | 더하기, 빼기, 곱하기, 나누기, 나머지, 거듭제곱 연산을 수행. |
관계 연산 | ==, !=, <, >, <=, >= | 같음, 같지 않음, 작음, 큼, 작거나 같음, 크거나 같음 비교를 수행. |
논리 연산 | and, or, not, ! | 논리 AND, OR, NOT 연산을 수행. |
정규식 매칭 | matches | 문자열이 정규식과 일치하는지 확인. 예: 'abc' matches '[a-z]+' |
삼항 연산자 | condition ? valueIfTrue : valueIfFalse | 조건에 따라 값을 선택. |
Elvis 연산자 | value ?: defaultValue | value가 null이면 defaultValue를 반환하고, 그렇지 않으면 value를 반환. |
Safe Navigation | object?.property | object가 null이면 NullPointerException을 발생시키지 않고 null을 반환. |
컬렉션 프로젝션 | collection.! [expression] | 컬렉션의 각 요소에 대해 expression을 평가하고, 그 결과로 구성된 새로운 컬렉션을 반환. 예: users.! [name] (모든 사용자의 이름 목록) |
컬렉션 선택 | collection.? [expression] | 컬렉션에서 expression을 만족하는 요소만 선택하여 새로운 컬렉션을 반환. 예: users.? [age > 18] (18세 초과인 사용자 목록) |
컬렉션 첫번째/마지막 | collection.^[expression], collection.$[expression] | 컬렉션에서 expression을 만족하는 첫 번째/마지막 요소를 찾음. |
T() 표현식 | T(ClassName) | ClassName의 static method, static field, 생성자를 호출할 수 있도록 해주는 표현식. |
'개발 > Spring' 카테고리의 다른 글
[Spring]Model vs RedirectAttributes (0) | 2025.03.16 |
---|---|
[Spring] Spring MVC 주요 어노테이션 (0) | 2025.03.16 |
[Spring] xml 설정 파일 예시 (0) | 2025.03.16 |
[Spring] 날짜 파라미터 처리하기 (0) | 2025.03.14 |
[Spring] Spring MVC 요청의 흐름 (0) | 2025.03.14 |