`
conkeyn
  • 浏览: 1504472 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

在自定义spring aop中使用el获取拦截方法的变量值。

阅读更多

参考自: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) {

    }

}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics