春のドキュメントから:
@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 より前
Spel 式のパラメーターの値を のようなものと連結することをお勧めしますkey="#checkWarehouse.toString() + #isbn.toString()")
。org.springframework.cache.interceptor.ExpressionEvaluator が Object を返すため、これは機能するはずです。これは後でキーとして使用されるため、提供する必要はありません。int
SPEL 式の an 。
衝突確率の高いハッシュコードはキーとして使えません。
このスレッドの誰かが使用を提案しまし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 が出力されます。
PS実際には、私たちが持っている参照ドキュメントで
@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 も参照してください。
正確さのために、そして楽しい数学的/コンピューター科学の事実として、組み込みハッシュとは異なり、MD5 や SHA256 などの安全な 暗号化ハッシュ関数を使用することを追加したいと思います。そのような関数のプロパティにより、これは絶対に可能です。ただし、毎回計算するにはコストがかかりすぎる可能性があります。詳細については、たとえば Dan Boneh 暗号化コースを参照してください。
Spring 3.2 でいくつかの限定的なテストを行った後、SpEL list: を使用できるようです{..., ..., ...}
。これには、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")