参考自:http://stackoverflow.com/questions/33024977/pass-method-argument-in-aspect-of-custom-annotation
经过梳理做成的DEMO,附件有完整示例。
package org.demo.el;
import org.demo.el.interceptor.CheckEntity;
public class Company {
private Long id;
private String name;
private Employee managingDirector;
public String getName() {
return name;
}
@CheckEntity(key = "#name")
public void setName(String name) {
this.name = name;
}
public Employee getManagingDirector() {
return managingDirector;
}
public void setManagingDirector(Employee managingDirector) {
this.managingDirector = managingDirector;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
package org.demo.el.interceptor;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CheckEntity {
String message() default "Check entity msg";
String key() default "#id";
}
package org.demo.el.interceptor;
import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.expression.AnnotatedElementKey;
import org.springframework.expression.EvaluationContext;
import org.springframework.stereotype.Component;
/**
* http://stackoverflow.com/questions/33024977/pass-method-argument-in-aspect-of-custom-annotation
*
*
*/
@Component
@Aspect
public class CheckEntityAspect {
protected final Log logger = LogFactory.getLog(getClass());
private ExpressionEvaluator<Long> evaluator = new ExpressionEvaluator<>();
@Before("execution(* *.*(..)) && @annotation(checkEntity)")
public void checkEntity(JoinPoint joinPoint, CheckEntity checkEntity) {
Long result = getValue(joinPoint, checkEntity.key());
logger.info("result: " + result);
System.out.println("running entity check: " + joinPoint.getSignature().getName());
}
private Long getValue(JoinPoint joinPoint, String condition) {
return getValue(joinPoint.getTarget(), joinPoint.getArgs(),
joinPoint.getTarget().getClass(),
((MethodSignature) joinPoint.getSignature()).getMethod(), condition);
}
private Long getValue(Object object, Object[] args, Class clazz, Method method,
String condition) {
if (args == null) {
return null;
}
EvaluationContext evaluationContext =
evaluator.createEvaluationContext(object, clazz, method, args);
AnnotatedElementKey methodKey = new AnnotatedElementKey(method, clazz);
return evaluator.condition(condition, methodKey, evaluationContext, Long.class);
}
}
package org.demo.el.interceptor;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
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;
public class ExpressionEvaluator<T> extends CachedExpressionEvaluator {
// shared param discoverer since it caches data internally
private final ParameterNameDiscoverer paramNameDiscoverer =
new DefaultParameterNameDiscoverer();
private final Map<ExpressionKey, Expression> conditionCache = new ConcurrentHashMap<>(64);
private final Map<AnnotatedElementKey, Method> targetMethodCache = new ConcurrentHashMap<>(64);
/**
* Create the suitable {@link EvaluationContext} for the specified event handling on the
* specified method.
*/
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);
}
/**
* Specify if the condition defined by the specified expression matches.
*/
public T condition(String conditionExpression, AnnotatedElementKey elementKey,
EvaluationContext evalContext, Class<T> 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;
}
}
package org.demo.el.interceptor;
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;
}
}
package org.demo;
/**
*
*/
import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
// @ActiveProfiles({"product"})
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestApp.class)
public abstract class AbsTestCase {
}
/**
*
*/
package org.demo;
import org.demo.el.Company;
import org.demo.el.interceptor.CheckEntity;
import org.springframework.stereotype.Service;
@Service
public class Service1 {
@CheckEntity(key = "#compay.id")
public void serviceMethod1(String name, Long id, Company compay) {
System.err.println("id: " + id + " ,name: " + name);
}
}
package org.demo;
import javax.annotation.Resource;
import org.demo.el.Company;
import org.junit.Test;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@EnableWebMvc
public class SpringTester extends AbsTestCase {
@Resource
private Service1 service1;
/**
* @throws Exception
*/
@Test
public void test1() throws Exception {
Company company = new Company();
company.setId(121L);
company.setName("company name1");
service1.serviceMethod1("name1", 1L, company);
System.err.println("test1()");
}
}
package org.demo;
/**
*
*/
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
@ComponentScan(basePackages = {"org.demo"})
@EnableAspectJAutoProxy
@SpringBootApplication
public class TestApp {
/**
* @param args
*/
public static void main(String[] args) {
}
}