Spring AOP和注释在方法执行之前检查参数

时间:2017-04-06 08:57:51

标签: java spring annotations aop spring-aop

如果方法参数是特定值,我必须抛出异常。 目的是锁定所有使用特定值的方法,所以我想使用Spring AOP,但我是新手。 我的问题是检索方法参数的值,我创建了这个样本:

注释

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAOPAnnotation {
}

AOP课程

@Component
@Aspect
public class TestAOP {

    @Before("@annotation(TestAOPAnnotation)")
    public void logAOP(){
        //Make some operations with database and throw exception in a specific case 
        throw new RuntimeException();
    }
}

我使用注释的方法

@Override
@TestAOPAnnotation
public List<Animals> findByName(String name) throws QueryException {
    try{
        return animalsRepository.findByName(name);
    }catch(Exception e){
        throw new QueryException(e);
    }
}

我抓住异常的地方

@Override
@RequestMapping(value="/test/{name}", method = RequestMethod.GET)
public @ResponseBody List<Animals> findByName(@PathVariable String name){
    try{
        return databaseAnimalsServices.findByName(name);
    }catch(QueryException e){
        return null;
    }catch(Exception e){
        //CATCH AOP EXCEPTION
        List<Animals> list = new ArrayList<Animals>();
        list.add(new Animals("AOP", "exception", "test"));
        return list;
    }
}

如何获取name参数?我可以在参数(或只有这个注释)上使用另一个注释,但我不知道如何。你能救我吗?

修改 要捕获参数注释,我可以使用:

@Before("execution(* *(@Param (*),..))")

但它只有在我知道参数顺序时才有效,而我只需要注释参数。 否则,到目前为止,最好的解决方案是

@Before("@annotation(TestAOPAnnotation) && args(name,..)")
public void logAOP(String name){
    System.out.println(name);
    throw new RuntimeException("error");
}

但参数必须是签名中的第一个

2 个答案:

答案 0 :(得分:1)

您可以使用可以访问调用数据的@Around建议。

@Around("@annotation(TestAOPAnnotation)")
public Object logAOP(ProceedingJoinPoint aPoint) throws Throwable {
    // First, implement your checking logic
    // aPoint.getArgs() may be inspected here ...
    if (...) {
        throw new RuntimeException(...);
    }

    // now, actually proceed with the method call
    return aPoint.proceed();
}

getArgs()使您可以访问传递给方法的真实参数。

答案 1 :(得分:0)

您可以从joinPoint获取调用参数:

@Around(.....)
public Object check(ProceedingJoinPoint joinPoint) {
    for (Object object : joinPoint.getArgs()) {
           .... add your checks here.
    }
    return joinPoint.proceed();

}

请注意,您无法从joinPoint轻松获取参数的名称(就像在.NET中一样),但您可以检查类型和值。

有关有效的执行模式,请参阅https://blog.espenberntsen.net/2010/03/20/aspectj-cheat-sheet/