복붙노트

[SPRING] Spring AOP를 사용하여 메소드 인수를 얻으시겠습니까?

SPRING

Spring AOP를 사용하여 메소드 인수를 얻으시겠습니까?

나는 Spring AOP를 사용하고 있고 aspect를 가지고있다 :

@Aspect
public class LoggingAspect {

    @Before("execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..))")
    public void logBefore(JoinPoint joinPoint) {

        System.out.println("logBefore() is running!");
        System.out.println("hijacked : " + joinPoint.getSignature().getName());
        System.out.println("******");
    }

}

위 aspect는 addCustomer 메소드 실행을 차단합니다. addCustomer 메소드는 문자열을 입력으로 사용합니다. 하지만 logBefore 메서드 안에 addCustomer 메서드에 전달 된 입력을 기록해야합니다. 그렇게 할 수 있습니까?

해결법

  1. ==============================

    1.몇 가지 옵션이 있습니다.

    몇 가지 옵션이 있습니다.

    먼저, 권고 된 메소드의 모든 인수를 포함하는 Object []를 리턴하는 JoinPoint # getArgs () 메소드를 사용할 수 있습니다. 당신이 그들과 함께하고 싶은 것에 따라 약간의 캐스팅을해야 할 수도 있습니다.

    둘째, args pointcut 표현식을 다음과 같이 사용할 수 있습니다 :

    // use '..' in the args expression if you have zero or more parameters at that point
    @Before("execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..)) && args(yourString,..)")
    

    당신의 방법은 다음과 같이 정의 될 수있다.

    public void logBefore(JoinPoint joinPoint, String yourString) 
    
  2. ==============================

    2.예, getArgs를 사용하여 인수 값을 찾을 수 있습니다.

    예, 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);
          ...
       }
    }
    
  3. ==============================

    3.많은 조언을 위해 하나의 pointcut을 정의하면 도움이 될 수있는 또 다른 방법이 있습니다 :

    많은 조언을 위해 하나의 pointcut을 정의하면 도움이 될 수있는 또 다른 방법이 있습니다 :

    @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());
    }
    
  4. ==============================

    4.귀하는 다음 방법 중 하나를 사용할 수 있습니다.

    귀하는 다음 방법 중 하나를 사용할 수 있습니다.

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

    또는

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

    joinpoint.getArgs ()는 객체 배열을 반환합니다. 입력은 단일 문자열이기 때문에 하나의 객체 만 반환됩니다.

    두 번째 접근법에서는 advice 메소드의 표현식과 입력 매개 변수에서 이름이 동일해야합니다. 즉 args (inputString) 및 public void logBefore2 (JoinPoint joinPoint, String inputString)

    여기서 addCustomer (String)는 하나의 String 입력 매개 변수가있는 메소드를 나타냅니다.

  5. ==============================

    5.단일 문자열 인수 인 경우 다음을 수행하십시오. joinPoint.getArgs () [0];

    단일 문자열 인수 인 경우 다음을 수행하십시오. joinPoint.getArgs () [0];

  6. ==============================

    6.모든 args를 기록해야하거나 메소드에 인수가 하나있는 경우 이전 대답에서 설명한 것처럼 getArgs를 간단히 사용할 수 있습니다.

    모든 args를 기록해야하거나 메소드에 인수가 하나있는 경우 이전 대답에서 설명한 것처럼 getArgs를 간단히 사용할 수 있습니다.

    특정 arg를 로그해야하는 경우이를 주석 처리하고 다음과 같이 값을 복구 할 수 있습니다.

    @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]);
            }
        }
     }
    }
    

    사용 예 :

    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
    }
    
  7. ==============================

    7.메소드 매개 변수와 해당 값을 가져올 수 있으며 다음 코드로 주석을 사용하여 주석을 추가 할 수 있습니다.

    메소드 매개 변수와 해당 값을 가져올 수 있으며 다음 코드로 주석을 사용하여 주석을 추가 할 수 있습니다.

    Map 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;
        }
    
  8. from https://stackoverflow.com/questions/15660535/get-method-arguments-using-spring-aop by cc-by-sa and MIT license