カスタムコメントサポートスプリングEL式


1    三つの注釈サポート類を追加しましたが、コピーしたspringの種類です.
package per.yan.ding.util.el;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.context.expression.AnnotatedElementKey;
import org.springframework.expression.EvaluationContext;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;

/**
 * @author gaoyan
 * @date 2019/1/14 17:41
 */
public class AspectSupportUtils {
    private static ExpressionEvaluator evaluator = new ExpressionEvaluator();

    public static Object getKeyValue(JoinPoint joinPoint, String keyExpression) {
        return getKeyValue(joinPoint.getTarget(), joinPoint.getArgs(), joinPoint.getTarget().getClass(),
                ((MethodSignature) joinPoint.getSignature()).getMethod(), keyExpression);
    }

    private static Object getKeyValue(Object object, Object[] args, Class> clazz, Method method,
                                      String keyExpression) {
        if (StringUtils.hasText(keyExpression)) {
            EvaluationContext evaluationContext = evaluator.createEvaluationContext(object, clazz, method, args);
            AnnotatedElementKey methodKey = new AnnotatedElementKey(method, clazz);
            return evaluator.key(keyExpression, methodKey, evaluationContext);
        }
        return SimpleKeyGenerator.generateKey(args);
    }
}
package per.yan.ding.util.el;

import org.springframework.aop.support.AopUtils;
import org.springframework.context.expression.AnnotatedElementKey;
import org.springframework.context.expression.CachedExpressionEvaluator;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author gaoyan
 * @date 2019/1/14 17:42
 */
public class ExpressionEvaluator extends CachedExpressionEvaluator {
    private final ParameterNameDiscoverer paramNameDiscoverer = new DefaultParameterNameDiscoverer();

    private final Map conditionCache = new ConcurrentHashMap<>(64);

    private final Map targetMethodCache = new ConcurrentHashMap<>(64);

    public EvaluationContext createEvaluationContext(Object object, Class> targetClass, Method method,
                                                     Object[] args) {
        Method targetMethod = getTargetMethod(targetClass, method);
        ExpressionRootObject root = new ExpressionRootObject(object, args);
        return new MethodBasedEvaluationContext(root, targetMethod, args, this.paramNameDiscoverer);
    }

    public Object key(String conditionExpression, AnnotatedElementKey elementKey, EvaluationContext evalContext) {
        return getExpression(this.conditionCache, elementKey, conditionExpression).getValue(evalContext);
    }

    private Method getTargetMethod(Class> targetClass, Method method) {
        AnnotatedElementKey methodKey = new AnnotatedElementKey(method, targetClass);
        Method targetMethod = this.targetMethodCache.get(methodKey);
        if (targetMethod == null) {
            targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
            if (targetMethod == null) {
                targetMethod = method;
            }
            this.targetMethodCache.put(methodKey, targetMethod);
        }
        return targetMethod;
    }
}
package per.yan.ding.util.el;

/**
 * @author gaoyan
 * @date 2019/1/14 17:42
 */
public class ExpressionRootObject {
    private final Object object;

    private final Object[] args;

    public ExpressionRootObject(Object object, Object[] args) {
        this.object = object;
        this.args = args;
    }

    public Object getobject() {
        return object;
    }

    public Object[] getArgs() {
        return args;
    }
}
2    カスタムコメントを追加し、ユーザー定義のタンジェント解析クラスで使用します.
package per.yan.ding.aspect;

import java.lang.annotation.*;

/**
 *         
 * @author gaoyan
 * @date 2019/1/15 10:02
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {

    String orderNoKey();

    String createdByKey() default "System";
}
package per.yan.ding.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import per.yan.ding.model.vo.DataResponse;
import per.yan.ding.util.el.AspectSupportUtils;

import java.lang.reflect.Method;

/**
 * @author gaoyan
 * @date 2019/1/15 10:05
 */
@Slf4j
@Aspect
@Component
public class LogAspect {

    public static final String USER_SYSTEM = "System";

    public static final int SUCCESS_CODE = 200;

    @Pointcut("@annotation(per.yan.ding.aspect.Log)")
    public void doPerform() {

    }

    @AfterReturning(pointcut = "doPerform()", returning = "result")
    public void determine(JoinPoint jp, Object result) {
        if (result instanceof DataResponse) {
            DataResponse response = (DataResponse) result;
            if (response.getResultCode() == SUCCESS_CODE) {
                MethodSignature signature = (MethodSignature) jp.getSignature();
                if (null != signature) {
                    Method method = signature.getMethod();
                    if (null != method && method.isAnnotationPresent(Log.class)) {
                        Log log = method.getAnnotation(Log.class);
                        String orderNoKey = log.orderNoKey();
                        String createdByKey = log.createdByKey();
                        //  spring EL          
                        String orderNo = (String) AspectSupportUtils.getKeyValue(jp, orderNoKey);
                        Integer createdBy;
                        if (USER_SYSTEM.equals(createdByKey)) {
                            createdBy = 0;
                        } else {
                            createdBy = (Integer) AspectSupportUtils.getKeyValue(jp, createdByKey);
                        }
                        /// TODO: 2019/3/29        service    

                    }
                }
            }
        }
    }
}