首页 > 解决方案 > 如何在springboot / java app中使用给定注释获取方法

问题描述

有没有办法直接获取在给定对象中使用给定注释注释的方法(非静态)?我不想遍历所有方法的列表并检查给定的注释是否存在。在下面的示例代码中,我使用了虚拟方法(不存在)getMethodAnnotatedWith()。我需要用实际方法替换它。

public class MyController {
  @PostMapping("/sum/{platform}")
  @ValidateAction
  public Result sum(@RequestBody InputRequest input, @PathVariable("platform") String platform) {
    log.info("input: {}, platform: {}", input, platform);
    return new Result(input.getA() + input.getB());
  }
}
class InputRequest {
  @NotNull
  private Integer a;
  @NotNull
  private Integer b;

  @MyValidator
  public boolean customMyValidator() {
    log.info("From customMyValidator-----------");
    return false;
  }
}
@Aspect
@Component
@Slf4j
public class AspectClass {
  @Before(" @annotation(com.example.ValidateAction)")
  public void validateAspect(JoinPoint joinPoint) throws Throwable {
    log.info(" MethodName : " + joinPoint.getSignature().getName());
    Object[] args = joinPoint.getArgs();
    log.info("args[0]==>"+args[0] +", args[1]==>"+args[1]);

    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    Method method = signature.getMethod();
    Parameter[] parameters = method.getParameters();
    Method customMyValidator = parameters[0].getType().getMethodAnnotatedWith(MyValidator.class);  // InputRequest class type which has a method annotated with @MyValidator

    customMyValidator.invoke(args[0]);
  }
}

标签: javareflectionspring-aop

解决方案


MethodUtils (Apache Commons Lang) 可用于实现需求。

示例代码中使用的 API:MethodUtils.getMethodsListWithAnnotation

方面代码

@Component
@Aspect
public class CallAnnotatedMethodAspect {

    @Pointcut("within(rg.so.q64604586.service.*) && @annotation(rg.so.q64604586.annotation.ValidateAction)")
    public void validateActionMethod() {
    };

    @Before("validateActionMethod() && args(request,..)")
    public void adviceMethod(InputRequest request)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        List<Method> methodList = MethodUtils.getMethodsListWithAnnotation(request.getClass(), MyValidator.class);
        for (Method m : methodList) {
            m.invoke(request, new Object[] {});
        }
    }
}

注意:注释的保留策略MyValidator是 RUNTIME 以使此代码正常工作。

如果InputRequest切面中获取的实例是代理,则需要修改代码以获取相同的实际类。


推荐阅读