Preface
As we all know, encache is the most popular Java open source caching framework now, with simple configuration, clear structure and powerful functions. By annotating @Cacheable, you can quickly add method results to the cache. The specified cache can be quickly cleared through @CacheEvict.
However, since the @CacheEvict annotation uses key-value and does not support fuzzy deletion, you will encounter problems. When I use @Cacheable to cooperate with Spring EL expressions, I add multiple caches of the same method, such as:
@GetMapping("/listOfTask/{page}/")@Cacheable(value = "BusinessCache", key = "'listOfTask_'+ #page")public ResponseMessage<PageTaskVO> getTaskList(@PathVariable("page") String page) { do something...}The above code is to get task information by paging. Use an EL expression to get the page in the parameter and use the cache key to add it to the cache of ehcache using @Cacheable. At this time, keys of the type listOfTask_1, listOfTask_2, listOfTask_3 will appear in the cache.
When adding or deleting tasks, the list will change. At this time, you need to remove all the caches related to listOfTask_*. At this time, I don’t know how much content related to listOfTask_* is cached in the cache, so it is impossible to call @CacheEvict to delete it one by one.
Since ehcache itself cannot support it, we can only implement it ourselves.
accomplish
Considering the cache added by using annotations, removing caches also uses annotation processing to maintain development consistency. Annotations are also very friendly to developers. Then we consider using custom annotations to blur batch removal of caches.
First, define the annotation CacheRemove:
@Target({ java.lang.annotation.ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)public @interface CacheRemove { String value(); String[] key();}Where, value is like ehcache, used to define the cache name to operate. A key is an array that stores regular expressions for multiple cached keys. The naming of CacheRemove is clear and easy to understand and does not conflict with the annotation of ehcache itself. The definition of the annotation ends here. Next, you need to deal with annotations. Because the spring framework is used, it is natural that you will think of using AOP to make annotations.
The purpose of the annotation is to batch blurred cache removal. The following two issues need to be considered:
The way I gave and the simplest way I think is:
First define the class name CacheRemoveAspect:
@Aspect@Componentpublic class CacheRemoveAspect { @Pointcut(value = "(execution(* *.*(..)) && @annotation(com.example.CacheRemove))") private void pointcut() {} do something...}Define a tangent in a slicing area, use execution(* *.*(..) && @annotation(com.example.CacheRemove)) to indicate that all annotated classes CacheRemove are executed, and the values in @annotation are the fully qualified names of the annotations.
After the point of incision is defined, the following highlight is the specific implementation of the section. Generally speaking, the cache will not be removed after the method of adding, deleting and modifying is executed. So use @AfterReturning() to implement it. The following things need to be done in the specific implementation:
The specific implementation is as follows:
@AfterReturning(value = "pointcut()")private void process(JoinPoint joinPoint){ MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); CacheRemove cacheRemove = method.getAnnotation(CacheRemove.class); if (cacheRemove != null){ String value = cacheRemove.value(); String[] keys = cacheRemove.key(); //Regular keys that need to be removed List cacheKeys = CacheUtils.cacheKeys(value); for (String key : keys){ Pattern pattern = Pattern.compile(key); for (Object cacheKey: cacheKeys) { String cacheKeyStr = String.valueOf(cacheKey); if (pattern.matcher(cacheKeyStr).find()){ CacheUtils.remove(value, cacheKeyStr); } } } } } }}The above is the specific implementation of ehcache fuzzy batch removal cache. Among them, BusinessCacheUtils encapsulates the ehcache tool class for itself. It mainly implements normal functions such as obtaining cache pools, obtaining caches, removing caches, adding caches, and viewing all caches. The code is as follows:
public class CacheUtils { private static CacheManager cacheManager = SpringContextHolder.getBean("ehCacheManagerFactory"); public static Object get(String cacheName, String key) { Element element = getCache(cacheName).get(key); return element == null ? null : element.getObjectValue(); } public static void put(String cacheName, String key, Object value) { Element element = new Element(key, value); getCache(cacheName).put(element); } public static void remove(String cacheName, String key) { getCache(cacheName).remove(key); } public static List cacheKeys(String cacheName){ return getCache(cacheName).getKeys(); } /** * Get a cache, if no one is created. * @param cacheName * @return */ private static Cache getCache(String cacheName) { Cache cache = cacheManager.getCache(cacheName); if (cache == null) { cacheManager.addCache(cacheName); cache = cacheManager.getCache(cacheName); cache.getCacheConfiguration().setEternal(true); } return cache; } public static CacheManager getCacheManager() { return cacheManager; }}At this point, the entire ehcache fuzzy batch removal function is implemented.
Summarize
The whole process has a simple idea, and after using some AOP knowledge, the required functions are completed. However, the specific removal of some codes can be considered for optimization. Through all the cache loops, all the caches that need to be removed are removed, instead of thinking that there are several keys like this, the full cache is traversed several times. The specific implementation is left to readers to complete. Hope it will be helpful to you. I also hope everyone will support Wulin.com more.