2013-03-27 20 views
35

Tôi đang sử dụng Spring AOP và có dưới khía cạnh:Nhận đối số phương pháp bằng cách sử dụng Spring AOP?

@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("******"); 
    } 

} 

Trên chặn khía cạnh addCustomer phương pháp thực hiện. Phương thức addCustomer lấy chuỗi làm đầu vào. Nhưng tôi cần đăng nhập đầu vào được chuyển đến phương thức addCustomer bên trong phương thức logBefore.
Có thể làm như vậy không?

+0

chữ ký phương pháp của 'AddCustomer là gì (..) '? –

Trả lời

46

Bạn có một vài lựa chọn:

Thứ nhất, bạn có thể sử dụng phương thức JoinPoint#getArgs() trả về một Object[] chứa tất cả các đối số của phương thức được khuyên. Bạn có thể phải làm một số đúc tùy thuộc vào những gì bạn muốn làm với họ.

Thứ hai, bạn có thể sử dụng các biểu args pointcut như vậy:

// 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,..)") 

sau đó phương pháp của bạn thay vì có thể được định nghĩa là

public void logBefore(JoinPoint joinPoint, String yourString) 
+2

Nếu tôi không nhầm, có sự khác biệt về hành vi giữa 2 tùy chọn. Cái thứ hai sẽ chỉ kích hoạt nếu arg tồn tại, trong khi cái đầu tiên sẽ được kích hoạt ngay cả khi đối số không tồn tại. –

+0

@SamuelEUSTACHI Chưa chỉ định biểu thức dấu vết cho ví dụ đầu tiên. Nếu chúng ta giả định thực thi 'addCustomer (..)', chắc chắn. Có thể không có đối số hoặc nhiều. –

15

Vâng, giá trị của bất kỳ đối số có thể được tìm thấy bằng 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); 
     ... 
    } 
} 
1

Nếu đó là một chuỗi đối số duy nhất, làm: joinPoint.getArgs()[0];

2

bạn có thể sử dụng một trong các phương pháp sau đây.

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

hoặc

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

joinpoint.getArgs() trả về mảng đối tượng. Vì, đầu vào là một chuỗi, chỉ một đối tượng được trả về.

Trong cách tiếp cận thứ hai, tên nên cùng trong biểu và tham số đầu vào trong phương pháp tư vấn ví dụ: args(inputString)public void logBefore2(JoinPoint joinPoint, String inputString)

Ở đây, addCustomer(String) cho biết phương pháp với tham số đầu vào một String.

2

Ngoài ra còn có một cách khác nếu bạn định nghĩa một pointcut cho nhiều lời khuyên có thể hữu ích:

@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

bạn có thể nhận tham số phương thức và giá trị của nó và nếu chú thích với một chú thích với đoạn mã sau:

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; 
    } 
1

Nếu bạn phải đăng nhập tất cả các args hoặc phương pháp của bạn của bạn đã một đối số, bạn có thể simpl y sử dụng getArgs như được mô tả trong các câu trả lời trước.

Nếu bạn phải đăng nhập một arg cụ thể, bạn có thể annoted nó và sau đó khôi phục lại giá trị của nó như thế này:

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

Ví dụ về sử dụng:

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 
} 
Các vấn đề liên quan