怎么自定义注解,支持Spring EL表达式,可以在idea中提示出来的??

2020-05-06 16:59发布

2条回答

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 get[removed]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记录日志

 

                    }

                }

            }

        }

    }

}


一周热门 更多>