Esto realmente me resulta interesante, como mucha gente desconoce el comportamiento de las anotaciones de Spring, las cuales trabajan dentro del contexto de nuestro contenedor Spring.

Es bastante curioso, como mucha gente pregunta, porque ciertas anotaciones no funcionan correctamente.

Por eso me dispongo a traeros un pequeño ejemplo con la anotación @Cacheable, creo que es la mejor forma de ilustrar esta «problemática»

Tenemos este código:

package com.apascualco.annotations.service;

import com.apascualco.annotations.domain.User;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

@Component
public class UserService {

    private List<User> users;

    public List<User> activeAllUsers() {
        System.out.println("Join activeAllUsers");
        return getAllUsers().stream()
                .peek(user -> user.setActive(true))
                .collect(Collectors.toList());
    }

    @Cacheable("users")
    public List<User> getAllUsers() {
        System.out.println("Join getAllUsers");
        return this.users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
}

Y por otro lado estos test, al final del post, tenéis un enlace al repo, con el ejemplo funcionando:

   @Test
    public void only_join_one_time() {
        userService.getAllUsers();
        userService.getAllUsers();
    }

    @Test
    public void join_two_time() {
        userService.getAllUsers();
        userService.activeAllUsers();
    }

Y aquí el resultado:

Se llama tres veces, como es posible, si lo tengo cacheado ?. Debería mantener el cache mientras el contexto este levantado!.

ESTO PASA CON TODAS LAS ANOTACIONES

Si nosotros llamamos internamente a la función, sin pasar por el contexto de Spring, la anotación es ignorada!.

En el método activeAllUsers, podemos ver claramente que llamamos a la función, sin utilizar el contexto de Spring, por ese motivo no funciona la anotación cacheable

CURIOSIDADES CON CACHEABLE

Aunque hablaré de este problema y como funciona el Cacheable más adelante, mirar este test:

    @Test
    public void modifying_cache() {
        final List<User> users = userService.getAllUsers();
        assertEquals("Users list should've 2 results", 2, users.size());
        users.remove(0);
        final List<User> userCache = userService.getAllUsers();
        assertEquals("Users list should've 1 results", 1, userCache.size());
    }

Pasará ?. Cacheable no devuelve un clon del objeto que cachea, por eso podéis modificarlo, entonces se verán afectadas posibles llamadas, por resultados que pueden ser no coherentes!.

IMPLEMENTACIÓN

Deja una respuesta