springframework

o.s.w IoC 핵심기술. SpEL (스프링 Expression Language)

Jungsoomin :) 2020. 9. 17. 00:35

SpEl 은 Spring Expression Language 의 약어이며 개인적으로 PropertySourcesPlaceholderConfigurer 를 사용할때 ${} 프로퍼티 식을 사용해본 경험으로 알고 있었다.

 


스프링 EL에 대해 학습한다. 객체 그래프를 조회하거나,  조작하는 기능을 제공한다.

 

#{} << 표현식

${} << 프로퍼티 = .properties 파일의 값을 가져와 파싱하여 집어넣는다.

 

를 사용한다.

 

  1. 메소드의 호출, 문자열 템플릿 기능을 제공하는 녀석이 스프링 전반에 걸쳐 필요하기에 만들어졌다.

  2. @Vaule 속성에 #{} < 표현식을 넣어 계산하거나 을 주거나 비교를 하는 등 jsp 의 EL과 비슷한점이 아주많다.

  3. eq , 숫자연산 리터럴 등을 넣어 파싱하는 것을 확인 할 수 있다.
import org.springframework.beans.factory.annotation.Value;
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 {

    @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;

    @Value("#{sample.data}")
    int sampleData;

    @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(sampleData);

        ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression("2 + 100");
       Integer value =  expression.getValue(Integer.class);

        System.out.println(value);

    }
}

단, 표현식 안에서는 프로퍼티 식을 이용하여 연산이나 이용이 가능하나. 프로퍼티가 표현식을 가질 수는 없다.

  • #{ ${} } << 가능

  • ${ #{} } << 불가능


이외에도 Map List 등 컬렉션에 대한 변환을 지원하니, 레퍼런스를 참고하는게 좋다.

 

Map > ExpressionParser 객체의 parse ("{name : 'soomin' age : '28'}")  = Object 리턴타입이므로 (Map) 캐스팅

List   > "{1, 2, ,3 ,4}" = (List) 캐스팅

 

물론 접근제한자에 따라 접근 제한이 갈리니 유의해야한다.

 

 

또한 Bean 을 참조하는 것 또한 가능하다.

@Component
public class Sample {

    public int data = 200;

}
@Value("#{sample.data}")
    int sampleData;

실제로 어디서 쓰이는가.

  1. 스프링 시큐리티 

  2. @Value 

  3. @ConditionalOnExpression : 선택적으로 빈을 읽어들일 때에 쓰임

스프링 시큐리티 의 사용.

@PreAuthorize @PostAuthorize @PreFilter @PostFilter , xml 인터셉터 URL 설정 등

 

스프링 데이터의 @Query

 


ExpressionParser, EvaluationContext를 이해하면 기반을 이해할 수 있다. 

  1. ExpressionParser 의 구현클래스 SpelExpressionParser .
  2. .parseExpression 메서드의 인자는 표현식처리 되므로 #{} 없이 문자열로 입력 한다.
  3. 리턴받은 Expression 객체getValue( Type.class ) 로 값을 변환받아온다.
@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(value);

    }

 


"변환"이라고 말씀해주실때 즈음에 ConversionService를 쓰는게 아닐까 싶었는데 맞다고 하신다!

 

Timeleaf...잠깐 읽어보았던 뷰 템플릿인 타임리프에서도 SpEl 를 지원한다고 한다.