본문 바로가기
Spring

[Spring] SpEL 사용법

by Amy IT 2022. 8. 22.

 

목차

     

    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;

     

     

     

    참고

     

    댓글