Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to customize annotations through spring-aop to realize the function of spring-cache

2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article is about how to customize annotations through spring-aop to achieve the function of spring-cache, the editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article.

Refer to several principles in the process of design:

The code has no intrusion.

Demand loading

Configuration diversification

First of all, customize the note: it only works on methods, and the runtime is valid. Key supports spel expressions, where FunctionEnum is an enumeration customized according to the business.

@ Target ({ElementType.METHOD}) @ Retention (RetentionPolicy.RUNTIME) @ Documentedpublic @ interface GlobalCache {/ * SPEL expression, cache key * @ return * / String key () default "; String value () default"; / * * current specific operations * eg: information addition, deletion, etc. * * @ return * / FunctionEnum functionEnum () default FunctionEnum.DEFAULT;}

To parse the current annotation by defining the aspect of aop, the core implementation is as follows

@ Around ("@ annotation (com.xxx.xxxx.core.foreign.annotation.GlobalCache)") public Object globalCacheAround (ProceedingJoinPoint joinPoint) {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes (); HttpServletRequest request = attributes.getRequest (); MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature (); Method method = methodSignature.getMethod (); ServiceData result; GlobalCache globalCache = method.getAnnotation (GlobalCache.class) String cacheKey = globalCache.functionEnum (). Name () + ":" + ForeignUtils.combineParam (methodSignature.getParameterNames (), joinPoint.getArgs (), globalCache.key (), String.class, "test-spel-123"); if ("GET" .equals (request.getMethod () {result = defaultRedisTemplate.opsForValue () .get (cacheKey) If (result! = null) {log.info ("hit cache, cached key: {}", cacheKey); return result;}} Map httpParams = ForeignUtils.builtParams (methodSignature.getParameterNames (), request) Result = CompletableFuture.supplyAsync (()-> {/ / redirect related operation return redirectUrl (cacheKey,request,httpParams,ForeignUtils.getRequestBody (method,joinPoint) }, LocalThreadPool.FOREIGN_EXEC_CACHE) .whenComplete ((serviceData, ex)-> {if (ex = = null) {/ / locally cached business processing notice.onSuccess (globalCache, httpParams, serviceData);} else {notice.onError (ex, serviceData); throw new ForeignInvokeException ("current request was deny...") }) .join (); return result;}

There are a lot of small piecemeal problems encountered in the process of construction, including how to parse the body in the PUT request, and so on. The code of the ForeignUtils utility class is attached below.

/ * * Assembly cache key * format: method name: parameter value 1: parameter value 2 * automatic parsing format * * @ param functionName name corresponding to the current operation * @ param args parameter * @ return * / public static String combineParameter (String functionName, Method method, Object [] args) {Class [] classArr = method.getParameterTypes () For (int index = 0; index < classArr.length; index++) {if (classArr [index] = = HttpServletRequest.class) {/ / is there anything else to ignore? Continue;} functionName + = ":" + args [index];} return functionName } / * key parameter: value parameter variable * title:test-123,subtitle:test-subtitle-123 * * @ param params * @ param request * @ return * / public static Map builtParams (String [] params, HttpServletRequest request) {Map keyMap = Maps.newHashMap (); for (int I = 0; I < params.length) String value +) {String value = request.getParameter (params [I]); if (StringUtils.isNotBlank (value)) {keyMap.put (params [I], value);}} return keyMap } / * * request parameters after assembling http. Placeholder method: * title= {title} & subtitle= {subtitle} * you can use queryString () instead of * * @ param httpParams * @ return * / public static String builtHttpParams (Map httpParams) {String result = "". For (Map.Entry entry: httpParams.entrySet ()) {result + = entry.getKey () + "= {" + entry.getKey () + "} &";} if (result.endsWith ("&")) {return result.substring (0, result.length ()-1);} return result } / * get the public static Object getRequestBody value in the current request * * @ param method * @ param joinPoint * @ return * / public static Object getRequestBody (Method method, ProceedingJoinPoint joinPoint) {Annotation [] [] currentAnnotionArr = method.getParameterAnnotations (); Object body = null; for (int index = 0; index < currentAnnotionArr.length) Index++) {try {if (currentAnnotionArr [index] [0] .annotationType () = = RequestBody.class) {body = joinPoint.getArgs () [index]; break;}} catch (Exception e) {}} return body } / * get the parameter pair of path in the request * @ param method * @ param joinPoint * @ return * / public static String getPathArgs (Method method, ProceedingJoinPoint joinPoint) {Annotation [] [] currentAnnotionArr = method.getParameterAnnotations (); String pathValue = null; for (int index = 0; index < currentAnnotionArr.length) Index++) {try {if (currentAnnotionArr [index] [0] .annotationType () = = PathVariable.class) {pathValue = String.valueOf (joinPoint.getArgs () [index]); break;}} catch (Exception e) {}} return pathValue } private static ExpressionParser parser = new SpelExpressionParser (); / * * parsing SPEL expression cache corresponding key information * * @ param params * @ param args * @ param spel * @ param clazz * @ param defaultResult * @ return * / public static T combineParam (String [] params, Object [] args, String spel, Class clazz, T defaultResult) {EvaluationContext context = new StandardEvaluationContext () For (int index = 0; index < params.length; index++) {context.setVariable (params [index], args [index]);} try {Expression expression = parser.parse_Expression (spel); return expression.getValue (context, clazz);} catch (Exception e) {return defaultResult;}}

The above tool classes are mainly related to parameter assembly, parsing, etc.

The above is how to customize annotations through spring-aop to achieve the function of spring-cache. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report