You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

100 lines
2.9 KiB

package com.xiaomage.aop;
import com.xiaomage.annotation.Lock;
import com.xiaomage.service.LockManager;
import com.xiaomage.vo.LockResult;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
/**
* 锁注释解析器
*
* @author Admin
* @date 2022/12/25
*/
@Aspect
@Component
@Slf4j
public class LockAnnotationParser {
@Resource
private LockManager lockManager;
/**
* 定义切点
*/
@Pointcut(value = "@annotation(com.xiaomage.annotation.Lock)")
private void cutMethod() {
}
/**
* 切点逻辑具体实现
*/
@Around(value = "cutMethod() && @annotation(lock)")
public Object parser(ProceedingJoinPoint point, Lock lock) throws Throwable {
String value = lock.value();
if (isEl(value)) {
value = getByEl(value, point);
}
LockResult lockResult = lockManager.lock(getRealLockKey(value), lock.expireTime(), lock.waitTime());
try {
return point.proceed();
} finally {
lockManager.unlock(lockResult.getRLock());
}
}
/**
* 解析 SpEL 表达式并返回其值
*/
private String getByEl(String el, ProceedingJoinPoint point) {
Method method = ((MethodSignature) point.getSignature()).getMethod();
String[] paramNames = getParameterNames(method);
Object[] arguments = point.getArgs();
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression(el);
EvaluationContext context = new StandardEvaluationContext();
for (int i = 0; i < arguments.length; i++) {
context.setVariable(paramNames[i], arguments[i]);
}
return expression.getValue(context, String.class);
}
/**
* 获取方法参数名列表
*/
private String[] getParameterNames(Method method) {
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
return u.getParameterNames(method);
}
private boolean isEl(String str) {
return str.contains("#");
}
/**
* 锁键值
*/
private String getRealLockKey(String value) {
return String.format("lock:%s", value);
}
}