All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.noir.common.lock.aop.DLockAnnotationAdvice Maven / Gradle / Ivy

package com.noir.common.lock.aop;

import com.noir.common.lock.DLockFactory;
import com.noir.common.lock.annotation.DLock;
import com.noir.common.lock.excptions.TryLockFailException;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

@Component
public class DLockAnnotationAdvice implements MethodInterceptor {
    @Autowired
    private DLockFactory lockFactory;

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        return doLock(invocation);
    }

    private Object doLock(MethodInvocation invocation) throws Throwable {
        Object[] args = invocation.getArguments();
        Method method = invocation.getMethod();
        Class clz = method.getDeclaringClass();

        DLock dLock = AnnotatedElementUtils.findMergedAnnotation(clz, DLock.class);
        DLock methodDLock = AnnotatedElementUtils.findMergedAnnotation(method, DLock.class);
        if (Objects.nonNull(methodDLock)) {
            dLock = methodDLock;
        }
        assert dLock != null;

        // 创建解析器
        ExpressionParser parser = new SpelExpressionParser();
        // 创建上下文
        StandardEvaluationContext ctx = creteCtx(method, args);

        List locks = Arrays.stream(dLock.value())
                .map(origin -> parseKey(parser, ctx, origin))
                .map(lockFactory::getLock)
                .collect(Collectors.toList());
        try {
            for (Lock lock:locks) {
                if (!lock.tryLock(dLock.timeOutSecond(), TimeUnit.SECONDS)) {
                    throw new TryLockFailException();
                }
            }
            return invocation.proceed();
        } finally {
            for (Lock lock:locks) {
                if (lock != null) {
                    lock.unlock();
                }
            }
        }
    }

    /**
     * SpEL解析
     */
    private String parseKey(ExpressionParser parser, StandardEvaluationContext ctx, String key) {
        if (StringUtils.isEmpty(key)) return "";
        return parser.parseExpression(key, new TemplateParserContext()).getValue(ctx, String.class);
    }

    /**
     * 初始化解析上下文
     */
    private StandardEvaluationContext creteCtx(Method method, Object[] args) {
        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
        String[] paraNameArr = u.getParameterNames(method);

        //SpEL上下文
        StandardEvaluationContext context = new StandardEvaluationContext();
        //把方法参数放入SpEL上下文中
        if (Objects.nonNull(paraNameArr)) {
            for (int i = 0; i < paraNameArr.length; i++) {
                context.setVariable(paraNameArr[i], args[i]);
            }
        }
        return context;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy