developer tip

여러 메서드 인수의 @Cacheable 키

optionbox 2020. 11. 30. 08:05
반응형

여러 메서드 인수의 @Cacheable 키


로부터 봄 문서 :

@Cacheable(value="bookCache", key="isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

어떻게 지정할 수 있습니다 @Cachable사용 isbn하고 checkWarehouse열쇠로?


업데이트 : 현재 Spring 캐시 구현은 달리 지정되지 않은 경우 모든 메서드 매개 변수를 캐시 키로 사용합니다. 선택한 키를 사용하려면고유 키를 만드는 가장 간단한 방법 인SpEL 목록사용하는 Arjan의 답변참조하십시오{#isbn, #includeUsed}.

에서 봄 문서

기본 키 생성 전략은 Spring 4.0 릴리스와 함께 변경되었습니다. 이전 버전의 Spring은 여러 키 매개 변수에 대해 매개 변수의 hashCode () 만 고려하고 equals ()는 고려하지 않는 키 생성 전략을 사용했습니다. 이로 인해 예기치 않은 키 충돌이 발생할 수 있습니다 (배경은 SPR-10237 참조). 새로운 'SimpleKeyGenerator'는 이러한 시나리오에 복합 키를 사용합니다.

Spring 4.0 이전

난 당신이 같은 뭔가 게임 무료 발현 매개 변수의 값을 CONCAT하는 것이 좋습니다 key="#checkWarehouse.toString() + #isbn.toString()"), 나는 이것이 당신이 제공 할 필요가 없습니다 나중에 키로 사용됩니다 org.springframework.cache.interceptor.ExpressionEvaluator 반환 개체로 일 것으로 판단 int당신의 SPEL 표현한다.

충돌 확률이 높은 해시 코드 는 키로 사용할 수 없습니다 .

이 스레드의 누군가가 사용을 제안 T(java.util.Objects).hash(#p0,#p1, #p2)했지만 작동하지 않으며이 접근 방식은 쉽게 깨집니다. 예를 들어 SPR-9377 의 데이터를 사용했습니다 .

    System.out.println( Objects.hash("someisbn", new Integer(109), new Integer(434)));
    System.out.println( Objects.hash("someisbn", new Integer(110), new Integer(403)));

두 줄 모두 내 환경에서 -636517714를 인쇄합니다.

추신 실제로 우리는 참조 문서에서

@Cacheable(value="books", key="T(someType).hash(#isbn)") 
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

이 예제는 잘못되고 오해의 소지가 있으며 키가 고유해야하므로 문서에서 제거해야한다고 생각합니다.

PPS는 또한 기본 키 생성에 관한 몇 가지 흥미로운 아이디어를 위해 https://jira.springsource.org/browse/SPR-9036참조 하십시오 .

나는 정확성을 위해 안전한 사용한다는 재미있는 사실로 추가 할 암호 해시 함수 때문에 이러한 함수의 특성, SHA256 같은 것은 IS 이 작업이 가능하지만, 모든 시간이 너무 비쌀 수를 계산.


Spring 3.2로 제한된 테스트를 거친 후 SpEL 목록을 사용할 수 있습니다 {..., ..., ...}.. 여기에는 null도 포함될 수 있습니다 . Spring은 목록을 실제 캐시 구현의 핵심으로 전달합니다. Ehcache를 사용할 때 어떤 시점에서 모든 항목을 고려하는 List # hashCode ()를 호출 합니다. (Ehcache 가 해시 코드 에만 의존 하는지 확실하지 않습니다 .)

나는 이것을 공유 캐시에 사용하는데 , 여기서 Spring 기본 키 생성기에 포함되지 않은 키에 메서드 이름도 포함 합니다. 이렇게하면 다른 방법에 대해 일치하는 키를 위험에 빠뜨리지 않고 (너무 많이 ...) (단일) 캐시를 쉽게 지울 수 있습니다. 처럼:

@Cacheable(value="bookCache", 
  key="{ #root.methodName, #isbn?.id, #checkWarehouse }")
public Book findBook(ISBN isbn, boolean checkWarehouse) 
...

@Cacheable(value="bookCache", 
  key="{ #root.methodName, #asin, #checkWarehouse }")
public Book findBookByAmazonId(String asin, boolean checkWarehouse)
...

물론 많은 메서드에서이 기능이 필요하고 항상 키에 모든 매개 변수를 사용하는 경우 클래스 및 메서드 이름을 포함하는 사용자 지정 키 생성기를 정의 할 수도 있습니다.

<cache:annotation-driven mode="..." key-generator="cacheKeyGenerator" />
<bean id="cacheKeyGenerator" class="net.example.cache.CacheKeyGenerator" />

...와:

public class CacheKeyGenerator 
  implements org.springframework.cache.interceptor.KeyGenerator {

    @Override
    public Object generate(final Object target, final Method method, 
      final Object... params) {

        final List<Object> key = new ArrayList<>();
        key.add(method.getDeclaringClass().getName());
        key.add(method.getName());

        for (final Object o : params) {
            key.add(o);
        }
        return key;
    }
}

예를 들어 JDK 1.7에서 Spring-EL 표현식을 사용할 수 있습니다.

@Cacheable(value="bookCache", key="T(java.util.Objects).hash(#p0,#p1, #p2)")

이것은 작동합니다

@Cacheable(value="bookCache", key="#checkwarehouse.toString().append(#isbn.toString())")

이것을 사용하십시오

@Cacheable(value="bookCache", key="#isbn + '_' + #checkWarehouse + '_' + #includeUsed")

참고 URL : https://stackoverflow.com/questions/14072380/cacheable-key-on-multiple-method-arguments

반응형