varargs parametros multiples argumentos java spring ehcache

multiples - parametros en java netbeans



@Tecla clave en mĂșltiples argumentos de mĂ©todo (5)

Después de algunas pruebas limitadas con Spring 3.2, parece que se puede usar una lista de SpEL: {..., ..., ...} . Esto también puede incluir valores null . Spring pasa la lista como la clave para la implementación de la memoria caché real. Al usar Ehcache, en algún momento invocará List#hashCode() , que toma en cuenta todos sus elementos. (No estoy seguro si Ehcache solo confía en el código hash).

Lo uso para un caché compartido, en el que también incluyo el nombre del método en la clave, que el generador de claves predeterminado de Spring no incluye . De esta manera, puedo borrar fácilmente la memoria caché (única), sin (demasiado) arriesgar las claves correspondientes para diferentes métodos. Me gusta:

@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) ...

Por supuesto, si muchos métodos lo necesitan y usted siempre está usando todos los parámetros para su clave, entonces también se puede definir un generador de claves personalizado que incluya la clase y el nombre del método:

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

...con:

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

De la documentación de primavera :

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

¿Cómo puedo especificar que @Cachable use isbn y checkWarehouse como clave?


Esto funcionará

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


Puede usar una expresión Spring-EL, por ejemplo, en JDK 1.7:

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


Utilizar esta

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


Actualización : la implementación de caché de Spring actual usa todos los parámetros de método como la clave de caché si no se especifica lo contrario. Si desea utilizar las teclas seleccionadas, consulte la respuesta de Arjan que utiliza la lista de {#isbn, #includeUsed} que es la forma más sencilla de crear claves únicas.

De la documentación de primavera

La estrategia de generación de claves predeterminada cambió con el lanzamiento de Spring 4.0. Las versiones anteriores de Spring usaban una estrategia de generación de claves que, para múltiples parámetros clave, solo consideraba el hashCode () de los parámetros y no equals (); esto podría causar colisiones de llave inesperadas (ver SPR-10237 para el fondo). El nuevo ''SimpleKeyGenerator'' usa una clave compuesta para tales escenarios.

Antes de la primavera 4.0

Te sugiero que concatenes los valores de los parámetros en la expresión de Spel con algo como key="#checkWarehouse.toString() + #isbn.toString()") , creo que esto debería funcionar como org.springframework.cache.interceptor.ExpressionEvaluator devuelve Object, que luego se utiliza como la clave, por lo que no es necesario que proporcione un int en su expresión SPEL.

En cuanto al código hash con una alta probabilidad de colisión, no puede usarlo como la clave.

Alguien en este hilo ha sugerido usar T(java.util.Objects).hash(#p0,#p1, #p2) pero NO FUNCIONARÁ y este enfoque es fácil de romper, por ejemplo, he usado los datos de 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)));

Ambas líneas imprimen -636517714 en mi entorno.

PD En realidad, en la documentación de referencia tenemos

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

Creo que este ejemplo es INCORRECTO y engañoso y debe eliminarse de la documentación, ya que las claves deben ser únicas.

PPS también consulta https://jira.springsource.org/browse/SPR-9036 para obtener algunas ideas interesantes sobre la generación de claves predeterminada.

Me gustaría agregar en aras de la corrección y como un hecho entretenido que el uso de una función de cifrado criptográfico seguro como SHA256, debido a las propiedades de dicha función ES POSIBLE para esta tarea, pero calcularla cada vez puede ser demasiado costoso.