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记录日志
}
}
}
}
}
}