【问题标题】:Spring AOP and annotation to check parameter before method executionSpring AOP和注解在方法执行前检查参数
【发布时间】:2017-04-06 08:57:50
【问题描述】:

如果方法参数是特定值,我必须抛出异常。 目的是锁定所有使用特定值的方法,所以我想使用 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;
    }
}

如何获取名称参数?我可能会在参数上使用另一个注释(或仅此注释),但我不知道如何。你能帮帮我吗?

编辑 要捕获参数注释,我可以使用:

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

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

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

但参数必须是签名中的拳头

【问题讨论】:

    标签: java spring annotations aop spring-aop


    【解决方案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() 让您可以访问传递给方法的真实参数。

    【讨论】:

      【解决方案2】:

      您可以从 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/ 了解有效的执行模式。

      【讨论】:

      • @RomanPuchkovskiy 我已经根据你的答案改变了我的答案,所以我支持你的答案。
      • 也许我错了,但是getArgs()我有参数值,所以我必须知道顺序
      • @luca 是的,您必须知道要查找的类型或值,您无法获得名称。
      • (a) 如果您知道签名中的哪个位置 - 从左或右计数(第 1、第 2、第 3 等) - 感兴趣的参数是,您应该使用与 @987654325 绑定的值@ 而不是使用丑陋的 joinPoint.getArgs() 调用与周围的循环。 (b) 我看不出参数名称有什么意义,因为参数名称会一直通过重构进行更改,但如果您绝对愿意,您可以使用-parameters 进行编译,然后通过反射获取参数名称。所以在 Jave/AspectJ 中不可能的说法是错误的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-30
      • 1970-01-01
      相关资源
      最近更新 更多