Spring Boot 自定义注解支持EL表达式(基于 MethodBasedEvaluationContext 实现)

您所在的位置:网站首页 springboot工具类用什么注解 Spring Boot 自定义注解支持EL表达式(基于 MethodBasedEvaluationContext 实现)

Spring Boot 自定义注解支持EL表达式(基于 MethodBasedEvaluationContext 实现)

#Spring Boot 自定义注解支持EL表达式(基于 MethodBasedEvaluationContext 实现)| 来源: 网络整理| 查看: 265

自定义注解

自定义 DistributeExceptionHandler 注解,该注解接收一个参数 attachmentId 。 该注解用在方法上,使用该注解作为切点,实现标注该注解的方法抛异常后的统一处理。

代码语言:javascript复制@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface DistributeExceptionHandler { String attachmentId(); }注解使用方法代码语言:javascript复制@DistributeExceptionHandler(attachmentId = "#test.id") public void test(Test test){ }Aspect代码

拦截 DistributeExceptionHandler 注解作为切点 使用 @AfterThrowing 处理异常情况

代码语言:javascript复制@Component @Aspect @Slf4j public class DistributeExceptionAspect { @Autowired private AttachmentContentClient attachmentContentClient; @Autowired private DistTaskService distTaskService; private ExpressionEvaluator evaluator = new ExpressionEvaluator(); @Pointcut("@annotation(DistributeExceptionHandler)") private void exceptionHandleMethod() { } @AfterThrowing(value = "exceptionHandleMethod()", throwing = "ex") public void doThrowing(JoinPoint joinPoint, Throwable ex) { log.error("捕获异常"); String attachmentId = getAttachmentId(joinPoint); // 获取 // 处理异常情况下的业务 } private DistributeExceptionHandler getDistributeExceptionHandler(JoinPoint joinPoint){ MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); return method.getAnnotation(DistributeExceptionHandler.class); } private String getAttachmentId(JoinPoint joinPoint) { DistributeExceptionHandler handler = getDistributeExceptionHandler(joinPoint); if (joinPoint.getArgs() == null) { return null; } EvaluationContext evaluationContext = evaluator.createEvaluationContext(joinPoint.getTarget(), joinPoint.getTarget().getClass(), ((MethodSignature) joinPoint.getSignature()).getMethod(), joinPoint.getArgs()); AnnotatedElementKey methodKey = new AnnotatedElementKey(((MethodSignature) joinPoint.getSignature()).getMethod(), joinPoint.getTarget().getClass()); return evaluator.condition(handler.attachmentId(), methodKey, evaluationContext, String.class); } }为注解添加Spring EL支持ExpressionRootObject代码语言:javascript复制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; } }ExpressionEvaluator代码语言:javascript复制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 T condition(String conditionExpression, AnnotatedElementKey elementKey, EvaluationContext evalContext, Class clazz) { return getExpression(this.conditionCache, elementKey, conditionExpression).getValue(evalContext, clazz); } 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; } }

参考:stackoverflow。

SPEL表达式计算引擎代码语言:javascript复制import org.springframework.beans.factory.BeanFactory; import org.springframework.context.expression.AnnotatedElementKey; import org.springframework.context.expression.BeanFactoryResolver; import org.springframework.context.expression.CachedExpressionEvaluator; import org.springframework.context.expression.MethodBasedEvaluationContext; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import java.lang.reflect.Method; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class SimpleExpressionEvaluator extends CachedExpressionEvaluator { private final Map conditionCache = new ConcurrentHashMap(64); public EvaluationContext createMethodBasedEvaluationContext(Method method, Object[] args, BeanFactory beanFactory) { MethodBasedEvaluationContext evaluationContext = new MethodBasedEvaluationContext(null, method, args, getParameterNameDiscoverer()); if (beanFactory != null) { evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory)); } return evaluationContext; } public T eval(String expression, AnnotatedElementKey elementKey, EvaluationContext evalContext) { return (T) getExpression(elementKey, expression).getValue(evalContext); } public Expression getExpression(AnnotatedElementKey elementKey, String expression) { return getExpression(this.conditionCache, elementKey, expression); } } // // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.context.expression; import java.util.Map; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; public abstract class CachedExpressionEvaluator { private final SpelExpressionParser parser; private final ParameterNameDiscoverer parameterNameDiscoverer; protected CachedExpressionEvaluator(SpelExpressionParser parser) { this.parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); Assert.notNull(parser, "SpelExpressionParser must not be null"); this.parser = parser; } protected CachedExpressionEvaluator() { this(new SpelExpressionParser()); } protected SpelExpressionParser getParser() { return this.parser; } protected ParameterNameDiscoverer getParameterNameDiscoverer() { return this.parameterNameDiscoverer; } protected Expression getExpression(Map cache, AnnotatedElementKey elementKey, String expression) { CachedExpressionEvaluator.ExpressionKey expressionKey = this.createKey(elementKey, expression); Expression expr = (Expression)cache.get(expressionKey); if (expr == null) { expr = this.getParser().parseExpression(expression); cache.put(expressionKey, expr); } return expr; } private CachedExpressionEvaluator.ExpressionKey createKey(AnnotatedElementKey elementKey, String expression) { return new CachedExpressionEvaluator.ExpressionKey(elementKey, expression); } protected static class ExpressionKey implements Comparable { private final AnnotatedElementKey element; private final String expression; protected ExpressionKey(AnnotatedElementKey element, String expression) { this.element = element; this.expression = expression; } public boolean equals(Object other) { if (this == other) { return true; } else if (!(other instanceof CachedExpressionEvaluator.ExpressionKey)) { return false; } else { CachedExpressionEvaluator.ExpressionKey otherKey = (CachedExpressionEvaluator.ExpressionKey)other; return this.element.equals(otherKey.element) && ObjectUtils.nullSafeEquals(this.expression, otherKey.expression); } } public int hashCode() { return this.element.hashCode() + (this.expression != null ? this.expression.hashCode() * 29 : 0); } public String toString() { return this.element + (this.expression != null ? " with expression \"" + this.expression : "\""); } public int compareTo(CachedExpressionEvaluator.ExpressionKey other) { int result = this.element.toString().compareTo(other.element.toString()); if (result == 0 && this.expression != null) { result = this.expression.compareTo(other.expression); } return result; } } }核心接口EvaluationContext代码语言:javascript复制// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.expression; import java.util.List; public interface EvaluationContext { TypedValue getRootObject(); List getConstructorResolvers(); List getMethodResolvers(); List getPropertyAccessors(); TypeLocator getTypeLocator(); TypeConverter getTypeConverter(); TypeComparator getTypeComparator(); OperatorOverloader getOperatorOverloader(); BeanResolver getBeanResolver(); void setVariable(String var1, Object var2); Object lookupVariable(String var1); }StandardEvaluationContext代码语言:javascript复制package org.springframework.expression.spel.support; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.core.convert.TypeDescriptor; import org.springframework.expression.BeanResolver; import org.springframework.expression.ConstructorResolver; import org.springframework.expression.EvaluationContext; import org.springframework.expression.MethodFilter; import org.springframework.expression.MethodResolver; import org.springframework.expression.OperatorOverloader; import org.springframework.expression.PropertyAccessor; import org.springframework.expression.TypeComparator; import org.springframework.expression.TypeConverter; import org.springframework.expression.TypeLocator; import org.springframework.expression.TypedValue; import org.springframework.util.Assert; public class StandardEvaluationContext implements EvaluationContext { private TypedValue rootObject; private List constructorResolvers; private List methodResolvers; private BeanResolver beanResolver; private ReflectiveMethodResolver reflectiveMethodResolver; private List propertyAccessors; private TypeLocator typeLocator; private TypeConverter typeConverter; private TypeComparator typeComparator = new StandardTypeComparator(); private OperatorOverloader operatorOverloader = new StandardOperatorOverloader(); private final Map variables = new HashMap(); public StandardEvaluationContext() { this.setRootObject((Object)null); } public StandardEvaluationContext(Object rootObject) { this.setRootObject(rootObject); } public void setRootObject(Object rootObject, TypeDescriptor typeDescriptor) { this.rootObject = new TypedValue(rootObject, typeDescriptor); } public void setRootObject(Object rootObject) { this.rootObject = rootObject != null ? new TypedValue(rootObject) : TypedValue.NULL; } public TypedValue getRootObject() { return this.rootObject; } public void setPropertyAccessors(List propertyAccessors) { this.propertyAccessors = propertyAccessors; } public List getPropertyAccessors() { this.ensurePropertyAccessorsInitialized(); return this.propertyAccessors; } public void addPropertyAccessor(PropertyAccessor accessor) { this.ensurePropertyAccessorsInitialized(); this.propertyAccessors.add(this.propertyAccessors.size() - 1, accessor); } public boolean removePropertyAccessor(PropertyAccessor accessor) { return this.propertyAccessors.remove(accessor); } public void setConstructorResolvers(List constructorResolvers) { this.constructorResolvers = constructorResolvers; } public List getConstructorResolvers() { this.ensureConstructorResolversInitialized(); return this.constructorResolvers; } public void addConstructorResolver(ConstructorResolver resolver) { this.ensureConstructorResolversInitialized(); this.constructorResolvers.add(this.constructorResolvers.size() - 1, resolver); } public boolean removeConstructorResolver(ConstructorResolver resolver) { this.ensureConstructorResolversInitialized(); return this.constructorResolvers.remove(resolver); } public void setMethodResolvers(List methodResolvers) { this.methodResolvers = methodResolvers; } public List getMethodResolvers() { this.ensureMethodResolversInitialized(); return this.methodResolvers; } public void addMethodResolver(MethodResolver resolver) { this.ensureMethodResolversInitialized(); this.methodResolvers.add(this.methodResolvers.size() - 1, resolver); } public boolean removeMethodResolver(MethodResolver methodResolver) { this.ensureMethodResolversInitialized(); return this.methodResolvers.remove(methodResolver); } public void setBeanResolver(BeanResolver beanResolver) { this.beanResolver = beanResolver; } public BeanResolver getBeanResolver() { return this.beanResolver; } public void setTypeLocator(TypeLocator typeLocator) { Assert.notNull(typeLocator, "TypeLocator must not be null"); this.typeLocator = typeLocator; } public TypeLocator getTypeLocator() { if (this.typeLocator == null) { this.typeLocator = new StandardTypeLocator(); } return this.typeLocator; } public void setTypeConverter(TypeConverter typeConverter) { Assert.notNull(typeConverter, "TypeConverter must not be null"); this.typeConverter = typeConverter; } public TypeConverter getTypeConverter() { if (this.typeConverter == null) { this.typeConverter = new StandardTypeConverter(); } return this.typeConverter; } public void setTypeComparator(TypeComparator typeComparator) { Assert.notNull(typeComparator, "TypeComparator must not be null"); this.typeComparator = typeComparator; } public TypeComparator getTypeComparator() { return this.typeComparator; } public void setOperatorOverloader(OperatorOverloader operatorOverloader) { Assert.notNull(operatorOverloader, "OperatorOverloader must not be null"); this.operatorOverloader = operatorOverloader; } public OperatorOverloader getOperatorOverloader() { return this.operatorOverloader; } public void setVariable(String name, Object value) { this.variables.put(name, value); } public void setVariables(Map variables) { this.variables.putAll(variables); } public void registerFunction(String name, Method method) { this.variables.put(name, method); } public Object lookupVariable(String name) { return this.variables.get(name); } public void registerMethodFilter(Class type, MethodFilter filter) throws IllegalStateException { this.ensureMethodResolversInitialized(); if (this.reflectiveMethodResolver != null) { this.reflectiveMethodResolver.registerMethodFilter(type, filter); } else { throw new IllegalStateException("Method filter cannot be set as the reflective method resolver is not in use"); } } private void ensurePropertyAccessorsInitialized() { if (this.propertyAccessors == null) { this.initializePropertyAccessors(); } } private synchronized void initializePropertyAccessors() { if (this.propertyAccessors == null) { List defaultAccessors = new ArrayList(); defaultAccessors.add(new ReflectivePropertyAccessor()); this.propertyAccessors = defaultAccessors; } } private void ensureConstructorResolversInitialized() { if (this.constructorResolvers == null) { this.initializeConstructorResolvers(); } } private synchronized void initializeConstructorResolvers() { if (this.constructorResolvers == null) { List defaultResolvers = new ArrayList(); defaultResolvers.add(new ReflectiveConstructorResolver()); this.constructorResolvers = defaultResolvers; } } private void ensureMethodResolversInitialized() { if (this.methodResolvers == null) { this.initializeMethodResolvers(); } } private synchronized void initializeMethodResolvers() { if (this.methodResolvers == null) { List defaultResolvers = new ArrayList(); this.reflectiveMethodResolver = new ReflectiveMethodResolver(); defaultResolvers.add(this.reflectiveMethodResolver); this.methodResolvers = defaultResolvers; } } }MethodBasedEvaluationContext代码语言:javascript复制// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.context.expression; import java.lang.reflect.Method; import java.util.Arrays; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.util.ObjectUtils; public class MethodBasedEvaluationContext extends StandardEvaluationContext { private final Method method; private final Object[] arguments; private final ParameterNameDiscoverer parameterNameDiscoverer; private boolean argumentsLoaded = false; public MethodBasedEvaluationContext(Object rootObject, Method method, Object[] arguments, ParameterNameDiscoverer parameterNameDiscoverer) { super(rootObject); this.method = method; this.arguments = arguments; this.parameterNameDiscoverer = parameterNameDiscoverer; } public Object lookupVariable(String name) { Object variable = super.lookupVariable(name); if (variable != null) { return variable; } else { if (!this.argumentsLoaded) { this.lazyLoadArguments(); this.argumentsLoaded = true; variable = super.lookupVariable(name); } return variable; } } protected void lazyLoadArguments() { if (!ObjectUtils.isEmpty(this.arguments)) { String[] paramNames = this.parameterNameDiscoverer.getParameterNames(this.method); int paramCount = paramNames != null ? paramNames.length : this.method.getParameterTypes().length; int argsCount = this.arguments.length; for(int i = 0; i < paramCount; ++i) { Object value = null; if (argsCount > paramCount && i == paramCount - 1) { value = Arrays.copyOfRange(this.arguments, i, argsCount); } else if (argsCount > i) { value = this.arguments[i]; } this.setVariable("a" + i, value); this.setVariable("p" + i, value); if (paramNames != null) { this.setVariable(paramNames[i], value); } } } } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3