Ich benutze Spring AOP und habe folgenden Aspekt:
@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("******");
}
}
Der obige Aspekt fängt die addCustomer
Ausführung der Methode ab. addCustomer
Methode nimmt String als Eingabe. Aber ich muss die Eingabe protokollieren, die an die addCustomer
Methode innerhalb der logBefore
Methode übergeben wurde.
Ist das möglich?
addCustomer(..)
?Antworten:
Sie haben einige Möglichkeiten:
Zunächst können Sie die
JoinPoint#getArgs()
Methode verwenden,Object[]
die alle Argumente der empfohlenen Methode zurückgibt . Je nachdem, was Sie mit ihnen machen möchten, müssen Sie möglicherweise ein Casting durchführen.Zweitens können Sie den
args
Pointcut-Ausdruck folgendermaßen verwenden:// 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,..)")
dann kann Ihre Methode stattdessen definiert werden als
public void logBefore(JoinPoint joinPoint, String yourString)
quelle
addCustomer(..)
, sicher. Kann keine oder viele Argumente sein.Ja, der Wert eines Arguments kann mit getArgs ermittelt werden
@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); ... } }
quelle
Wenn Sie alle Argumente protokollieren müssen oder Ihre Methode ein Argument hat, können Sie einfach getArgs verwenden, wie in den vorherigen Antworten beschrieben.
Wenn Sie ein bestimmtes Argument protokollieren müssen, können Sie es mit Anmerkungen versehen und dann seinen Wert wie folgt wiederherstellen:
@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]); } } } }
Anwendungsbeispiele:
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 }
quelle
"..."
bedeutet komplett mit Ihrem Muster.Es gibt auch eine andere Möglichkeit, wenn Sie einen Pointcut für viele Ratschläge definieren. Dies kann hilfreich sein:
@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()); }
quelle
Sie können eine der folgenden Methoden verwenden.
@Before("execution(* ong.customer.bo.CustomerBo.addCustomer(String))") public void logBefore1(JoinPoint joinPoint) { System.out.println(joinPoint.getArgs()[0]); }
oder
@Before("execution(* ong.customer.bo.CustomerBo.addCustomer(String)), && args(inputString)") public void logBefore2(JoinPoint joinPoint, String inputString) { System.out.println(inputString); }
joinpoint.getArgs () gibt ein Objektarray zurück. Da die Eingabe eine einzelne Zeichenfolge ist, wird nur ein Objekt zurückgegeben.
Beim zweiten Ansatz sollte der Name in Ausdruck und Eingabeparameter in der Beratungsmethode, dh
args(inputString)
und , identisch seinpublic void logBefore2(JoinPoint joinPoint, String inputString)
Hier
addCustomer(String)
gibt die Methode mit einem String-Parameter.quelle
Wenn es sich um ein einzelnes String-Argument handelt, gehen Sie wie folgt vor:
joinPoint.getArgs()[0];
quelle
Sie können den Methodenparameter und seinen Wert abrufen und wenn er mit einer Anmerkung mit folgendem Code versehen ist:
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; }
quelle
Wenn Sie @Aspect verwenden, können Sie diese Methode in Ihren Aspekt einfügen und den JoinPoint sowie den Namen des gewünschten Parameters senden.
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; }
und das Anrufbeispiel:
Object parameterObject = getParameter(joinPoint, "nameClient"); if ( Objects.nonNull(parameterObject) ) { String parametro = String.valueOf(parameterObject); }
Sie müssen nur den Objekttyp kennen, der konvertiert werden soll
quelle