2013-03-27 16 views
35

Sto usando primavera AOP e hanno sotto aspetto:Ottieni gli argomenti del metodo utilizzando 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("******"); 
    } 

} 

Sopra intercetta aspetto addCustomer metodo di esecuzione. Il metodo addCustomer accetta la stringa come input. Ma ho bisogno di registrare l'input passato al metodo addCustomer all'interno del metodo logBefore.
È possibile farlo?

+0

Qual è la firma del metodo di 'addCustomer (..) '? –

risposta

46

avete alcune opzioni:

In primo luogo, è possibile utilizzare il metodo JoinPoint#getArgs() che restituisce uno Object[] contenente tutti gli argomenti del metodo consigliato. Potresti dover fare un casting a seconda di cosa vuoi fare con loro.

In secondo luogo, è possibile utilizzare l'espressione args pointcut in questo modo:

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

allora il vostro metodo può invece essere definito come

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

Se non sbaglio, c'è una differenza di comportamento tra le 2 opzioni. Il secondo si innescherà solo se esiste l'arg, mentre il primo verrà innescato anche se l'argomento non esiste. –

+0

@ SamuelEUSTACHI Non ho specificato un'espressione pointcut per il primo esempio. Se assumiamo un'esecuzione di 'addCustomer (..)', sicuro. Non ci sono argomenti o molti. –

15

Sì, il valore di qualsiasi argomento si possono trovare utilizzando 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

Se si tratta di un singolo argomento stringa, fare: joinPoint.getArgs()[0];

2

tuo grado di utilizzare uno dei seguenti metodi.

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

o

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

joinpoint.getArgs() restituisce matrice oggetto. Poiché l'input è una stringa singola, viene restituito solo un oggetto.

Nel secondo approccio, il nome dovrebbe essere lo stesso di espressione e parametro di input nel metodo consigli cioè args(inputString) e public void logBefore2(JoinPoint joinPoint, String inputString)

Qui, addCustomer(String) indica il metodo con parametro di input una stringa.

2

C'è anche un altro modo se si definisce una pointcut per molti consigli può essere utile:

@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

è possibile ottenere parametro di metodo e il suo valore e se annotato con un'annotazione con seguente codice:

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

Se devi loggarti tutti args o la vostra tuo metodo hanno un argomento, si può Simpl y usa getArgs come descritto nelle risposte precedenti.

Se devi loggarti un arg specifico, è possibile annotata e poi recuperare il suo valore in questo modo:

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

Esempi di utilizzo:

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 
} 
Problemi correlati