목차
SpEL 이란?
SpEL은 Spring Expression Language의 약자로서 런타임에서 객체에 대한 쿼리와 조작(querying and manipulating)을 지원하는 강력한 표현 언어입니다. XML 기반 설정, 어노테이션 기반 설정, 자바코드에서 모두 사용 가능합니다.
SpEL 표기법
#{ SpEL표현식 }
SpEL은 기본적으로 #{}로 표기하며 괄호 안의 내용을 SpEL 표현식으로 인식해서 evaluation(평가, 실행) 합니다.
SpEL 지원 기능
- Literal expressions : 리터럴 표현식
- Boolean and relational operators : Boolean과 관계 연산자
- Regular expressions : 정규 표현식
- Class expressions : 클래스 표현식
- Accessing properties, arrays, lists, and maps : 프로퍼티, 배열, 리스트, 맵에 대한 접근
- Method invocation : 메소드 호출
- Relational operators : 관계연산자
- Assignment : 할당
- Calling constructors : 생성자 호출
- Bean references : 빈 참조
- Array construction : 배열 생성
- Inline lists : 인라인 리스트
- Inline maps : 인라인 맵
- Ternary operator : 삼항 연산자
- Variables : 변수
- User-defined functions : 사용자 정의 함수
- Collection Projection : 컬렉션 프로젝션
- Collection Selection : 컬렉션 셀렉션
- Templated expressions : 템플릿 표현식
Literal expressions : 리터럴 표현식
@Value("#{'홍길동'}")
String username;
@Value("#{10}")
int age;
@Value("#{72.6}")
double weight;
@Value("#{false}")
boolean isMarried;
Operators : 연산자
연산자 종류 | 기호 혹은 문자 |
산술 | +, -, *, / (div), % (mod), ^ |
관계 | < (lt), <= (le), > (gt), >= (ge), == (eq), != (ne) |
논리 | && (and), or (||), not (!) |
조건 | ?: |
정규식 | matches |
Mathematical Operators : 산술 연산자
@Value("#{1 + 1}") //2.0
private double addition;
@Value("#{1 - -3}") //4.0
private double subtraction;
@Value("#{5 % 3}") //2.0
private double modulus;
@Value("#{1 + 2 * 3}") //7.0
private double precedence;
Relational Operators : 관계 연산자
@Value("#{1 == 1}") //true
private boolean equal;
@Value("#{2 < 1}") //false
private boolean lessthan;
Logical Operators : 논리 연산자
@Value("#{!true}") //false
private boolean notTrue;
Ternary Operator : 삼항 연산자
@Value("#{true ? 'trueExp' : 'falseExp'}") //trueExp
private String trueString;
The Elvis Operator : 엘비스 연산자
//Elvis operator - shortening of the ternary operator syntax
@Value("#{true ?: 'falseExp'}") //true
private String elvis;
Bean References : 빈 참조
Person.java
@Component
public class Person {
@Value("#{'홍길동'}")
private String username;
public String getUsername() {
return username;
}
public String getXXX() {
return "getXXX()리턴값";
}
}
PersonTest.java
@Component
public class PersonTest {
@Value("#{person}") //#{빈id}
private Person person;
@Value("#{person.username}") //#{빈id.프로퍼티}
private String testName;
@Value("#{person.getXXX()}") //#{빈id.메소드명}
private String testString;
@Override
public String toString() {
return "PersonTest [person=" + person + ", testName=" + testName + ", testString=" + testString + "]";
}
}
TestMain.java
public class TestMain {
public static void main(String[] args) {
ApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationContext.xml");
PersonTest p = ctx.getBean("personTest", PersonTest.class);
System.out.println(p);
//PersonTest [person=com.dto.Person@74fe5c40, testName=홍길동, testString=getXXX()리턴값]
}
}
Class expressions : 클래스 표현식
//use the special T operator to specify an instance of java.lang.Class
//Static methods 호출 가능
@Value("#{T(java.lang.String)}") //class java.lang.String
private Class stringClass;
@Value("#{T(String).valueOf(10)}") //문자열 10
private String staticMethodCall;
@Value("#{T(java.lang.Math).random()*100}") //37.33210749843872
private double staticMethodCall2;
Properties : 프로퍼티
test.properties
db.driver=sampleDriverClass
db.url=sampleDBUrl
db.username=sampleDBUrl
db.password=sampleDBUrl
<util:properties> 태그 이용 빈으로 등록
applicationContext.xml
<!-- properties 빈 등록 -->
<!-- 패키지 경로 지정시 ex. com/test/test.properties -->
<util:properties id="properties" location="test.properties"></util:properties>
Test.java
//#{빈id['프로퍼티Key']}
@Value("#{properties['db.driver']}") //sampleDriverClass
private String driver;
@Value("#{properties['db.url']}") //sampleDBUrl
private String url;
@Value("#{properties['db.username']}") //sampleDBUsername
private String username;
@Value("#{properties['db.password']}") //sampleDBPassword
private String password;
<context:property-placeholder> 태그 이용 외부 프로퍼티 파일 로딩
applicationContext.xml
<!-- 외부 properties 파일 로딩 -->
<!-- 패키지 경로 지정시 ex. com/test/test.properties -->
<context:property-placeholder location="test.properties"/>
Test.java (SpEL 사용 X)
//${프로퍼티Key} - property placeholder syntax
@Value("${db.driver}") //sampleDriverClass
private String driver;
@Value("${db.url}") //sampleDBUrl
private String url;
@Value("${db.username}") //sampleDBUsername
private String username;
@Value("${db.password}") //sampleDBPassword
private String password;
Test.java (SpEL 사용 O)
//#{} 표현식 안에서 ${} 속성값 참조 가능
//#{'${프로퍼티Key}'}
@Value("#{'${db.driver}'}") //sampleDriverClass
private String driver;
@Value("#{'${db.url}'}") //sampleDBUrl
private String url;
@Value("#{'${db.username}'}") //sampleDBUsername
private String username;
@Value("#{'${db.password}'}") //sampleDBPassword
private String password;
Collection : 컬렉션
Collection References : 컬렉션 참조
MemberList.java
@Component
public class MemberList {
private List<String> members = new ArrayList<String>();
private Map<String, Integer> membersAge = new HashMap<String, Integer>();
public MemberList() {
members.add("홍길동");
members.add("이순신");
membersAge.put("홍길동", 10);
membersAge.put("이순신", 20);
}
//Getters and Setters
}
Test.java
@Value("#{memberList.members.size()}") //2
private int memberListSize;
@Value("#{memberList.members[0]}") //홍길동
private String firstMember;
@Value("#{memberList.membersAge['이순신']}") //20
private int ageOfLee;
Collection Selection : 컬렉션 셀렉션
Person.java
public class Person {
private String username;
private int age;
public Person(String username, int age) {
super();
this.username = username;
this.age = age;
}
@Override
public String toString() {
return "Person [username=" + username + ", age=" + age + "]";
}
//Getters and Setters
}
MemberList.java
@Component
public class MemberList {
private List<Person> members = new ArrayList<Person>();
private Map<String, Integer> membersAge = new HashMap<String, Integer>();
public MemberList() {
members.add(new Person("홍길동", 10));
members.add(new Person("이순신", 20));
members.add(new Person("유관순", 30));
members.add(new Person("강감찬", 40));
membersAge.put("홍길동", 10);
membersAge.put("이순신", 20);
membersAge.put("유관순", 30);
membersAge.put("강감찬", 40);
}
//Getters and Setters
}
Test.java
// .?[selectionExpression] - filters the collection and returns a new collection that contains a subset of the original elements
@Value("#{memberList.members.?[username=='홍길동']}") //[Person [username=홍길동, age=10]]
private List<Person> list1;
@Value("#{memberList.members.?[age>20]}") //[Person [username=유관순, age=30], Person [username=강감찬, age=40]]
private List<Person> list2;
@Value("#{memberList.membersAge.?[key=='홍길동']}") //{홍길동=10}
private Map<String, Integer> map1;
@Value("#{memberList.membersAge.?[value gt 20]}") //{강감찬=40, 유관순=30}
private Map<String, Integer> map2;
Collection Projection : 컬렉션 프로젝션
// .![projectionExpression] - lets a collection drive the evaluation of a sub-expression, resulting in a new collection
@Value("#{memberList.members.![username]}") //[홍길동, 이순신, 유관순, 강감찬]
private List<String> list1;
@Value("#{memberList.members.![username+' '+age]}") //[홍길동 10, 이순신 20, 유관순 30, 강감찬 40]
private List<String> list2;
@Value("#{memberList.members.?[age>20].![username]}") //[유관순, 강감찬]
private List<String> list3;
@Value("#{memberList.membersAge.![key]}") //[홍길동, 강감찬, 이순신, 유관순]
private List<String> mapList1;
@Value("#{memberList.membersAge.?[value gt 20].![key+':'+value]}") //[강감찬:40, 유관순:30]
private List<String> mapList2;
참고
- https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions
- https://atoz-develop.tistory.com/entry/Spring-SpEL-Spring-Expression-Language
- https://devwithpug.github.io/spring/spring-spel/
- https://developyo.tistory.com/57
- https://stackoverflow.com/questions/5322632/spring-expression-language-spel-with-value-dollar-vs-hash-vs
'Spring' 카테고리의 다른 글
[Spring] DB 연동 - MyBatis (0) | 2022.08.27 |
---|---|
[Spring] DB 연동 - JDBC (0) | 2022.08.25 |
[Spring] 의존성 주입(Dependency Injection) - (2) 어노테이션 기반 설정 (0) | 2022.08.21 |
[Spring] XML 기반 설정 의존 객체 자동 주입 (autowire) (0) | 2022.08.17 |
[Spring] 의존성 주입(Dependency Injection) - (1) XML 기반 설정 (0) | 2022.08.14 |
댓글