Получить аргументы метода с помощью Spring AOP?
Я использую 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
. Метод addCustomer
принимает строку как входной. Но мне нужно регистрировать ввод, переданный методу logBefore
внутри метода logBefore
.
Можно ли это сделать?
- Spring Контроллеры на основе аннотаций не работают, если они находятся внутри файла jar
- Java EE 6 vs. Spring 3 stack
- Как добиться условного импорта ресурсов в контексте Spring XML?
- Spring Boot и несколько внешних файлов конфигурации
- Как вернуть пользовательский объект из запроса Spring JPA GROUP BY
- Разбор JSON весной MVC с использованием Jackson JSON
- Ошибка ручки 404 с регулятором пружины
- Шаблон Spring JDBC для вызова хранимых процедур
- Как зарегистрировать class annotated Spring @Configuration вместо файла applicationContext.xml в web.xml?
- SpringBoot - создание файлов jar - нет classов автоматической настройки, найденных в META-INF / spring.factories
- Нужно сбросить значение последовательности в Oracle
- Как работает автомастер весной?
- Как ввести карту с помощью annotations @Value Spring?
У вас есть несколько вариантов:
Во-первых, вы можете использовать метод JoinPoint#getArgs()
который возвращает Object[]
содержащий все аргументы рекомендуемого метода. Возможно, вам придется делать кастинг в зависимости от того, что вы хотите с ними делать.
Во-вторых, вы можете использовать выражение pointcut 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)
Да, значение любого аргумента можно найти с помощью 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); ... } }
Существует и другой способ, если вы определите один 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()); }
Вы можете использовать один из следующих способов.
@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.
Если вам нужно зарегистрировать все аргументы или ваш метод имеет один аргумент, вы можете просто использовать 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 }
Если это единственный аргумент String, выполните: joinPoint.getArgs()[0];
вы можете получить параметр метода и его значение и аннотировать аннотацию следующим кодом:
Map
….
private Map getAnnotatedParameterValue(Method method, Object[] args) { Map 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; }