基於AOP和Redis實現的簡易版分散式鎖(二)
在上一篇文章ofollow,noindex">基於AOP和Redis實現的簡易版分散式鎖 中我們已經介紹了實現一個簡易版的分散式鎖。
那麼本文主要來講,如何將註解LockAnnotation和LockParamAnnotation合二為一,在LockAnnotation新增lockKey()方法來實現原本需要通過LockParamAnnotation來實現的鎖的唯一主鍵。
本次優化主要是引入了Spel。
LockAnnotation主要改動就是添加了lockKey()方法。
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.TYPE}) public @interface LockAnnotation { /** * 加鎖的key的字首 * * @return */ String lockField() default ""; /** * 鎖自動釋放時間,單位s * * @return */ int lockTime() default 3; /** * 加鎖的key的值 * @return */ String lockKey() default ""; }
LockAspect主要改動是獲取lockKey的方式,和之前不同的是目前lockKey的值的由註解上的lockKey()中的spel語法實現。
ExpressionParser parser = new SpelExpressionParser(); LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer(); EvaluationContext context = new StandardEvaluationContext(); Object[] args = joinPoint.getArgs(); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); String[] params = discoverer.getParameterNames(signature.getMethod()); for (int len = 0; len < params.length; len++) { context.setVariable(params[len], args[len]); } Expression expression = parser.parseExpression(lockAnnotation.lockKey()); String lockKey = expression.getValue(context, String.class);
使用方式和之前的區別也只在於兩個註解合併。lockKey的命名儘量保持'x='+#x的方式。
如果變數是個物件,需要獲取到物件中的值,例如是order物件中的orderSn,可以通過order.orderSn方式獲取。
@LockAnnotation(lockField = "lock", lockTime = 10, lockKey = "'orderSn='+#orderSn") public Integer lock(String action, String orderSn) { System.out.println(action); return 1; }
需要注意的是,常量'orderSn='需要用單引號',否則會被當做是賦值語法,而#後面的orderSn只要和方法中的變數名orderSn保持一直就可以了。
最後感謝好友樊金龍給的合併註解的建議,這才有了本次優化。
歡迎大家繼續提建議,如有采納,會在文末感謝。