Get method arguments using Spring AOP?

后端 未结 8 1972
陌清茗
陌清茗 2020-11-29 01:13

I am using Spring AOP and have below aspect:

@Aspect
public class LoggingAspect {

    @Before(\"execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..         


        
相关标签:
8条回答
  • 2020-11-29 01:43

    Your can use either of the following methods.

    @Before("execution(* ong.customer.bo.CustomerBo.addCustomer(String))")
    public void logBefore1(JoinPoint joinPoint) {
        System.out.println(joinPoint.getArgs()[0]);
     }
    

    or

    @Before("execution(* ong.customer.bo.CustomerBo.addCustomer(String)), && args(inputString)")
    public void logBefore2(JoinPoint joinPoint, String inputString) {
        System.out.println(inputString);
     }
    

    joinpoint.getArgs() returns object array. Since, input is single string, only one object is returned.

    In the second approach, the name should be same in expression and input parameter in the advice method i.e. args(inputString) and public void logBefore2(JoinPoint joinPoint, String inputString)

    Here, addCustomer(String) indicates the method with one String input parameter.

    0 讨论(0)
  • 2020-11-29 01:45

    Yes, the value of any argument can be found using getArgs

    @Before("execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..))")
    public void logBefore(JoinPoint joinPoint) {
    
       Object[] signatureArgs = thisJoinPoint.getArgs();
       for (Object signatureArg: signatureArgs) {
          System.out.println("Arg: " + signatureArg);
          ...
       }
    }
    
    0 讨论(0)
  • 2020-11-29 01:47

    you can get method parameter and its value and if annotated with a annotation with following code:

    Map<String, Object> annotatedParameterValue = getAnnotatedParameterValue(MethodSignature.class.cast(jp.getSignature()).getMethod(), jp.getArgs()); ....

    private Map<String, Object> getAnnotatedParameterValue(Method method, Object[] args) {
            Map<String, Object> annotatedParameters = new HashMap<>();
            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
            Parameter[] parameters = method.getParameters();
    
            int i = 0;
            for (Annotation[] annotations : parameterAnnotations) {
                Object arg = args[i];
                String name = parameters[i++].getDeclaringExecutable().getName();
                for (Annotation annotation : annotations) {
                    if (annotation instanceof AuditExpose) {
                        annotatedParameters.put(name, arg);
                    }
                }
            }
            return annotatedParameters;
        }
    
    0 讨论(0)
  • 2020-11-29 01:48

    If you have to log all args or your method have one argument, you can simply use getArgs like described in previous answers.

    If you have to log a specific arg, you can annoted it and then recover its value like this :

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.PARAMETER)
    public @interface Data {
     String methodName() default "";
    }
    
    @Aspect
    public class YourAspect {
    
     @Around("...")
     public Object around(ProceedingJoinPoint point) throws Throwable {
      Method method = MethodSignature.class.cast(point.getSignature()).getMethod();
      Object[] args = point.getArgs();
      StringBuilder data = new StringBuilder();
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        for (int argIndex = 0; argIndex < args.length; argIndex++) {
            for (Annotation paramAnnotation : parameterAnnotations[argIndex]) {
                if (!(paramAnnotation instanceof Data)) {
                    continue;
                }
                Data dataAnnotation = (Data) paramAnnotation;
                if (dataAnnotation.methodName().length() > 0) {
                    Object obj = args[argIndex];
                    Method dataMethod = obj.getClass().getMethod(dataAnnotation.methodName());
                    data.append(dataMethod.invoke(obj));
                    continue;
                }
                data.append(args[argIndex]);
            }
        }
     }
    }
    

    Examples of use :

    public void doSomething(String someValue, @Data String someData, String otherValue) {
        // Apsect will log value of someData param
    }
    
    public void doSomething(String someValue, @Data(methodName = "id") SomeObject someData, String otherValue) {
        // Apsect will log returned value of someData.id() method
    }
    
    0 讨论(0)
  • 2020-11-29 01:51

    if your using @Aspect an option is add this method inside your Aspect and send the JoinPoint and the name of parameter you need.

    private Object getParameter(ProceedingJoinPoint joinPoint, String parameterName) {
        Object valueParameter = null;
        if (Objects.nonNull(joinPoint) && joinPoint.getSignature() instanceof MethodSignature
                && Objects.nonNull(parameterName) ) {
            MethodSignature method = (MethodSignature)joinPoint.getSignature();
            String[] parameters = method.getParameterNames();
            for (int t = 0; t< parameters.length; t++) {
                if( Objects.nonNull(parameters[t]) && parameters[t].equals(parameterName)) {
                    Object[] obj = joinPoint.getArgs();
                    valueParameter = obj[t];
                }
            }
        }
        return valueParameter;
    }
    

    and the call example:

    Object parameterObject = getParameter(joinPoint, "nameClient");
    if ( Objects.nonNull(parameterObject) ) {
        String parametro = String.valueOf(parameterObject);
    }
    

    Only need know the type of object for convert

    0 讨论(0)
  • 2020-11-29 02:00

    There is also another way if you define one pointcut for many advices it can be helpful:

    @Pointcut("execution(@com.stackoverflow.MyAnnotation * *(..))")
    protected void myPointcut() {
    }
    
    @AfterThrowing(pointcut = "myPointcut() && args(someId,..)", throwing = "e")
    public void afterThrowingException(JoinPoint joinPoint, Exception e, Integer someId) {
        System.out.println(someId.toString());
    }
    
    @AfterReturning(pointcut = "myPointcut() && args(someId,..)")
    public void afterSuccessfulReturn(JoinPoint joinPoint, Integer someId) {
        System.out.println(someId.toString());
    }
    
    0 讨论(0)
提交回复
热议问题