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
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);
|
|
}
|
|
|
|
|
|
}
|
|
|