Loading...
Spring Framework Reference Documentation 7.0.2의 Properties, Arrays, Lists, Maps, and Indexers의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
Spring Expression Language는 객체 그래프를 탐색하고 다양한 구조에 대한 인덱싱을 지원합니다.
숫자 인덱스 값은 Java에서 배열의 n번째 요소에 접근할 때와 같이 0부터 시작합니다.
null-safe 연산자를 사용하여 객체 그래프를 탐색하고 다양한 구조에 대해 인덱스를 수행하는 방법에 대한 자세한 내용은 Safe Navigation Operator 섹션을 참조하십시오.
객체 그래프 내에서 프로퍼티 참조는 중첩된 프로퍼티 값을 나타내기 위해 마침표를 사용하여 탐색할 수 있습니다. Inventor 클래스의 인스턴스인 pupin과 tesla는
Classes used in the examples 섹션에 나열된 데이터로 채워졌습니다.
객체 그래프를 아래로 탐색하여 Tesla의 출생 연도와 Pupin의 출생 도시를 가져오기 위해 다음 표현식을 사용합니다:
1// evaluates to 1856 2int year = (Integer) parser.parseExpression("birthdate.year + 1900").getValue(context); 3 4// evaluates to "Smiljan" 5String city = (String) parser.parseExpression("placeOfBirth.city").getValue(context);
1// evaluates to 1856 2val year = parser.parseExpression("birthdate.year + 1900").getValue(context) as Int 3 4// evaluates to "Smiljan" 5val city = parser.parseExpression("placeOfBirth.city").getValue(context) as String
프로퍼티 이름의 첫 글자에 대해서는 대소문자를 구분하지 않아도 됩니다. 따라서 위의 예제에서 표현식은 각각
Birthdate.Year + 1900및<br>PlaceOfBirth.City로 작성할 수 있습니다. 추가로, 프로퍼티는 선택적으로 메서드 호출을 통해 접근할 수 있습니다. 예를 들어,<br>placeOfBirth.city대신getPlaceOfBirth().getCity()를 사용할 수 있습니다.
배열 또는 Set이나 List와 같은 컬렉션의 n번째 요소는 다음 예제에서 보이는 것처럼 대괄호 표기법을 사용하여 얻을 수 있습니다.
인덱스가 지정된 컬렉션이
java.util.List인 경우, n번째 요소는list.get(n)을 통해 직접 접근됩니다.<br>다른 어떤 타입의Collection에 대해서도, n번째 요소는 컬렉션의Iterator를 사용하여 컬렉션을 순회하고<br>만나게 되는 n번째 요소를 반환함으로써 접근됩니다.
1ExpressionParser parser = new SpelExpressionParser(); 2EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build(); 3 4// Inventions Array 5 6// evaluates to "Induction motor" 7String invention = parser.parseExpression("inventions[3]").getValue( 8 context, tesla, String.class); 9 10// Members List 11 12// evaluates to "Nikola Tesla" 13String name = parser.parseExpression("members[0].name").getValue( 14 context, ieee, String.class); 15 16// List and Array Indexing 17 18// evaluates to "Wireless communication" 19String invention = parser.parseExpression("members[0].inventions[6]").getValue( 20 context, ieee, String.class);
1val parser = SpelExpressionParser() 2val context = SimpleEvaluationContext.forReadOnlyDataBinding().build() 3 4// Inventions Array 5 6// evaluates to "Induction motor" 7val invention = parser.parseExpression("inventions[3]").getValue( 8 context, tesla, String::class.java) 9 10// Members List 11 12// evaluates to "Nikola Tesla" 13val name = parser.parseExpression("members[0].name").getValue( 14 context, ieee, String::class.java) 15 16// List and Array Indexing 17 18// evaluates to "Wireless communication" 19val invention = parser.parseExpression("members[0].inventions[6]").getValue( 20 context, ieee, String::class.java)
문자열의 n번째 문자(character)는 다음 예제에서 보이는 것처럼 대괄호 안에 인덱스를 지정하여 얻을 수 있습니다.
문자열의 n번째 문자는
java.lang.Character가 아니라java.lang.String으로 평가됩니다.
1// evaluates to "T" (8th letter of "Nikola Tesla") 2String character = parser.parseExpression("members[0].name[7]") 3 .getValue(societyContext, String.class);
1// evaluates to "T" (8th letter of "Nikola Tesla") 2val character = parser.parseExpression("members[0].name[7]") 3 .getValue(societyContext, String::class.java)
맵의 내용은 대괄호 안에 키 값을 지정하여 얻을 수 있습니다. 다음 예제에서 officers 맵의 키는 문자열이므로, 'president'와 같은 문자열 리터럴을 지정할 수 있습니다:
1// Officer's Map 2 3// evaluates to Inventor("Pupin") 4Inventor pupin = parser.parseExpression("officers['president']") 5 .getValue(societyContext, Inventor.class); 6 7// evaluates to "Idvor" 8String city = parser.parseExpression("officers['president'].placeOfBirth.city") 9 .getValue(societyContext, String.class); 10 11String countryExpression = "officers['advisors'][0].placeOfBirth.country"; 12 13// setting values 14parser.parseExpression(countryExpression) 15 .setValue(societyContext, "Croatia"); 16 17// evaluates to "Croatia" 18String country = parser.parseExpression(countryExpression) 19 .getValue(societyContext, String.class);
1// Officer's Map 2 3// evaluates to Inventor("Pupin") 4val pupin = parser.parseExpression("officers['president']") 5 .getValue(societyContext, Inventor::class.java) 6 7// evaluates to "Idvor" 8val city = parser.parseExpression("officers['president'].placeOfBirth.city") 9 .getValue(societyContext, String::class.java) 10 11val countryExpression = "officers['advisors'][0].placeOfBirth.country" 12 13// setting values 14parser.parseExpression(countryExpression) 15 .setValue(societyContext, "Croatia") 16 17// evaluates to "Croatia" 18val country = parser.parseExpression(countryExpression) 19 .getValue(societyContext, String::class.java)
객체의 프로퍼티는 대괄호 안에 프로퍼티의 이름을 지정하여 얻을 수 있습니다. 이는 키를 기반으로 맵의 값을 접근하는 것과 유사합니다. 다음 예제는 특정 프로퍼티를 가져오기 위해 객체에 대해 인덱스 하는 방법을 보여줍니다.
1// Create an inventor to use as the root context object. 2Inventor tesla = new Inventor("Nikola Tesla"); 3 4// evaluates to "Nikola Tesla" 5String name = parser.parseExpression("#root['name']") 6 .getValue(context, tesla, String.class);
1// Create an inventor to use as the root context object. 2val tesla = Inventor("Nikola Tesla") 3 4// evaluates to "Nikola Tesla" 5val name = parser.parseExpression("#root['name']") 6 .getValue(context, tesla, String::class.java)
Spring Framework 6.2부터 Spring Expression Language는 개발자가 IndexAccessor를 구현하고 이를 EvaluationContext에 등록할 수 있도록 함으로써 커스텀 구조에 대한 인덱싱을 지원합니다. 커스텀 인덱스 접근자에 의존하는 표현식의
compilation을 지원하려면, 해당 인덱스 접근자가 CompilableIndexAccessor SPI를 구현해야 합니다.
일반적인 사용 사례를 지원하기 위해 Spring은 대상 객체의 인덱스된 구조를 읽고 선택적으로 쓸 수 있는 유연한 IndexAccessor인 내장 ReflectiveIndexAccessor를 제공합니다. 인덱스된 구조는 (읽을 때) public 읽기 메서드를 통해 또는 (쓸 때) public 쓰기 메서드를 통해 접근할 수 있습니다.
읽기 메서드와 쓰기 메서드 사이의 관계는 인덱스된 구조의 일반적인 구현에 적용 가능한 관례에 기반합니다.
ReflectiveIndexAccessor는 읽기 접근에 대해 바이트코드로의 compilation을 지원하기 위해CompilableIndexAccessor도 구현합니다. 그러나 컴파일이 성공하려면 구성된 읽기 메서드가public클래스 또는public인터페이스를 통해 호출 가능해야 한다는 점에 유의하십시오.
다음 코드 목록은 Color enum과 FruitMap 타입을 정의합니다. FruitMap은 맵처럼 동작하지만 java.util.Map 인터페이스를 구현하지 않습니다. 따라서 SpEL 표현식 내에서 FruitMap에 대해 인덱스를 수행하려면 IndexAccessor를 등록해야 합니다.
1public enum Color { 2 RED, ORANGE, YELLOW 3}
1public class FruitMap { 2 3 private final Map<Color, String> map = new HashMap<>(); 4 5 public FruitMap() { 6 this.map.put(Color.RED, "cherry"); 7 this.map.put(Color.ORANGE, "orange"); 8 this.map.put(Color.YELLOW, "banana"); 9 } 10 11 public String getFruit(Color color) { 12 return this.map.get(color); 13 } 14 15 public void setFruit(Color color, String fruit) { 16 this.map.put(color, fruit); 17 } 18}
FruitMap에 대한 읽기 전용 IndexAccessor는 new ReflectiveIndexAccessor(FruitMap.class, Color.class, "getFruit")를 통해 생성할 수 있습니다. 해당 접근자가 등록되고 FruitMap이 #fruitMap이라는 이름의 변수로 등록되면, SpEL 표현식 #fruitMap[T(example.Color).RED]는 "cherry"로 평가됩니다.
FruitMap에 대한 읽기-쓰기 IndexAccessor는 new ReflectiveIndexAccessor(FruitMap.class, Color.class, "getFruit", "setFruit")를 통해 생성할 수 있습니다. 해당 접근자가 등록되고 FruitMap이 #fruitMap이라는 이름의 변수로 등록되면, SpEL 표현식 #fruitMap[T(example.Color).RED] = 'strawberry'를 사용하여 color red에 대한 fruit 매핑을 "cherry"에서 "strawberry"로 변경할 수 있습니다.
다음 예제는 FruitMap에 대해 인덱스를 수행하기 위해 ReflectiveIndexAccessor를 등록한 다음 SpEL 표현식 내에서 FruitMap에 대해 인덱스를 수행하는 방법을 보여줍니다.
1// Create a ReflectiveIndexAccessor for FruitMap 2IndexAccessor fruitMapAccessor = new ReflectiveIndexAccessor( 3 FruitMap.class, Color.class, "getFruit", "setFruit"); 4 5// Register the IndexAccessor for FruitMap 6context.addIndexAccessor(fruitMapAccessor); 7 8// Register the fruitMap variable 9context.setVariable("fruitMap", new FruitMap()); 10 11// evaluates to "cherry" 12String fruit = parser.parseExpression("#fruitMap[T(example.Color).RED]") 13 .getValue(context, String.class);
1// Create a ReflectiveIndexAccessor for FruitMap 2val fruitMapAccessor = ReflectiveIndexAccessor( 3 FruitMap::class.java, Color::class.java, "getFruit", "setFruit") 4 5// Register the IndexAccessor for FruitMap 6context.addIndexAccessor(fruitMapAccessor) 7 8// Register the fruitMap variable 9context.setVariable("fruitMap", FruitMap()) 10 11// evaluates to "cherry" 12val fruit = parser.parseExpression("#fruitMap[T(example.Color).RED]") 13 .getValue(context, String::class.java)
Literal Expressions
Inline Lists