我正在使用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("******");
}
}
以上方面拦截addCustomer
方法执行。 addCustomer
方法将字符串作为输入。
但我需要记录addCustomer
方法中传递给logBefore
方法的输入
是否可以这样做?
答案 0 :(得分:71)
您有几个选择:
首先,您可以使用JoinPoint#getArgs()
方法返回包含建议方法的所有参数的Object[]
。您可能需要进行一些投射,具体取决于您对它们的处理方式。
其次,您可以使用args
切入点表达式,如下所示:
// 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)
答案 1 :(得分:18)
是的,可以使用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);
...
}
}
答案 2 :(得分:6)
如果为许多建议定义一个切入点,还有另一种方法可以提供帮助:
@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());
}
答案 3 :(得分:5)
如果你必须记录所有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
}
答案 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()返回对象数组。因为,输入是单个字符串,所以只返回一个对象。
在第二种方法中,通知方法中的表达式和输入参数的名称应相同,即args(inputString)
和public void logBefore2(JoinPoint joinPoint, String inputString)
这里,addCustomer(String)
表示带有一个String输入参数的方法。
答案 5 :(得分:3)
如果是单个String参数,请执行以下操作:
joinPoint.getArgs()[0];
答案 6 :(得分:1)
您可以获取方法参数及其值,如果使用以下代码的注释进行注释:
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;
}
答案 7 :(得分:1)
如果使用@Aspect,则在您的Aspect中添加此方法,然后发送JoinPoint和所需的参数名称。
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;
}
和通话示例:
Object parameterObject = getParameter(joinPoint, "nameClient");
if ( Objects.nonNull(parameterObject) ) {
String parametro = String.valueOf(parameterObject);
}
只需要知道要转换的对象的类型