Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make the cache name in Spring cache configurable?

We use Spring cache framework for caching, and we'd like to able to support multiple namespaces for caches, such as "book", or "isbn", with the cache namespaces being configurable, rather than hardcoded in the class, like, instead of having

@Cacheable({ "book","isbn"})
public Book findBook(ISBN isbn) {...}

we want to be able somehow inject the cache name from a properties file, so that the cache name can be dynamically set, like:

@Cacheable({ #cachename1, #cachename2})
public Book findBook(ISBN isbn) {...}

I'm using SpEL here, but don't know if this is doable at all.

like image 855
David Zhao Avatar asked Nov 02 '12 05:11

David Zhao


2 Answers

Going off smartwjw's answer...

I was looking to have cacheNames resolved via spring environment variables, such as @Cacheable("${my.config.property.name}"). I accomplished this via a custom CacheResolver

import java.util.Collection;
import java.util.stream.Collectors;

import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.SimpleCacheResolver;
import org.springframework.core.env.PropertyResolver;

public class PropertyResolvingCacheResolver
    extends SimpleCacheResolver {

    private final PropertyResolver propertyResolver;

    protected PropertyResolvingCacheResolver(CacheManager cacheManager, PropertyResolver propertyResolver) {
        super(cacheManager);
        this.propertyResolver = propertyResolver;
    }

    @Override
    protected Collection<String> getCacheNames(CacheOperationInvocationContext<?> context) {
        Collection<String> unresolvedCacheNames = super.getCacheNames(context);
        return unresolvedCacheNames.stream()
            .map(unresolvedCacheName -> propertyResolver.resolveRequiredPlaceholders(unresolvedCacheName)).collect(Collectors.toList());
    }
}

And then of course you must configure it as THE CacheResolver to use with a @Configuration that extends org.springframework.cache.annotation.CachingConfigurerSupport.

@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {

    public static final String PROPERTY_RESOLVING_CACHE_RESOLVER_BEAN_NAME = "propertyResolvingCacheResolver";

    @Autowired
    private CacheManager cacheManager;
    @Autowired
    private Environment springEnv;

    @Bean(PROPERTY_RESOLVING_CACHE_RESOLVER_BEAN_NAME)
    @Override
    public CacheResolver cacheResolver() {
        return new PropertyResolvingCacheResolver(cacheManager, springEnv);
    }
}
like image 116
JeffNelson Avatar answered Oct 29 '22 15:10

JeffNelson


Spring 4.1 introduces CacheResolver, and use your self defined CacheResolver to select Cache then can be dynamic. spring 4.1 cache impovements

like image 39
vr3C Avatar answered Oct 29 '22 15:10

vr3C