Saltar al contenido

Spring Cache @Cacheable: no funciona al llamar desde otro método del mismo bean

Presta atención porque en este post vas a encontrar la solución que buscas.Esta noticia fue aprobado por nuestros expertos para asegurar la calidad y exactitud de nuestro contenido.

Solución:

Creo que así es como funciona. Por lo que recuerdo haber leído, se genera una clase de proxy que intercepta todas las solicitudes y responde con el valor almacenado en caché, pero las llamadas ‘internas’ dentro de la misma clase no obtendrán el valor almacenado en caché.

De https://code.google.com/p/ehcache-spring-annotations/wiki/UsingCacheable

Solo se interceptan las llamadas a métodos externos que llegan a través del proxy. Esto significa que la autoinvocación, en efecto, un método dentro del objeto de destino que llama a otro método del objeto de destino, no conducirá a una intercepción de caché real en tiempo de ejecución incluso si el método invocado está marcado con @Cacheable.

Desde Spring 4.3, el problema podría resolverse utilizando el autocableado sobre @Resource anotación:

@Component
@CacheConfig(cacheNames = "SphereClientFactoryCache")
public class CacheableSphereClientFactoryImpl implements SphereClientFactory 

    /**
     * 1. Self-autowired reference to proxified bean of this class.
     */
    @Resource
    private SphereClientFactory self;

    @Override
    @Cacheable(sync = true)
    public SphereClient createSphereClient(@Nonnull TenantConfig tenantConfig) 
        // 2. call cached method using self-bean
        return self.createSphereClient(tenantConfig.getSphereClientConfig());
    

    @Override
    @Cacheable(sync = true)
    public SphereClient createSphereClient(@Nonnull SphereClientConfig clientConfig) 
        return CtpClientConfigurationUtils.createSphereClient(clientConfig);
    

El siguiente ejemplo es lo que uso para acceder al proxy desde el mismo bean, es similar a la solución de @mario-eis, pero lo encuentro un poco más legible (tal vez no lo sea:-). De todos modos, me gusta mantener las anotaciones @Cacheable en el nivel de servicio:

@Service
@Transactional(readOnly=true)
public class SettingServiceImpl implements SettingService {

@Inject
private SettingRepository settingRepository;

@Inject
private ApplicationContext applicationContext;

@Override
@Cacheable("settingsCache")
public String findValue(String name) 
    Setting setting = settingRepository.findOne(name);
    if(setting == null)
        return null;
    
    return setting.getValue();


@Override
public Boolean findBoolean(String name) 
    String value = getSpringProxy().findValue(name);
    if (value == null) 
        return null;
    
    return Boolean.valueOf(value);


/**
 * Use proxy to hit cache 
 */
private SettingService getSpringProxy() 
    return applicationContext.getBean(SettingService.class);

...

Véase también Comenzar una nueva transacción en Spring bean

¡Haz clic para puntuar esta entrada!
(Votos: 1 Promedio: 5)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *