MelleD
MelleD

Reputation: 767

Call another method in Spring Aspect

I would like to convert a parameter and then call second method with this parameter. The convention would be that there is always the same method overloaded with the specific type. The idea is to solve it with Spring AOP.

@Component
public class ExampleAspect {

  @Around( "@annotation(Example)" )
  public Object test( final ProceedingJoinPoint joinPoint ) throws Throwable {
    final MethodSignature signature = (MethodSignature) joinPoint.getSignature();

    final Method method = signature.getMethod();

    final Example example = method.getAnnotation( Example.class );
    final Object[] args = joinPoint.getArgs();
    final String test = args[example.value()].toString();
    final Bar bar = convertToBar(test)
    args[example.value()] = bar;

    //ReflectionUtils?
    // call getBar(Bar bar)
    //return joinPoint.proceed( args );
  }
}

Here is the service

  @Example(0)
  public Object getBar(String test) {}

  public Object getBar(Bar test) {}

Are there any better options or ideas?

EDIT:

Cannot inject the target bean, because this AOP should be used by more than specific target bean.

1 possible solution not sure if there is a smarter solution

  @Around("@annotation(Example)")
  public Object test(final ProceedingJoinPoint joinPoint) throws Throwable {
    final MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    final Method method = signature.getMethod();

    final Example example = method.getAnnotation(Example.class);
    final Object[] args = joinPoint.getArgs();
    final String bar = args[example.value()].toString();
    final Bar aspectModelUrn = convertFromStringToBar(bar);
    args[example.value()] = bar;

    final Class<?>[] parameterTypes = method.getParameterTypes();
    parameterTypes[example.value()] = Bar.class;
    final Method newMethod = ReflectionUtils.findMethod(joinPoint.getTarget().getClass(), method.getName(), parameterTypes);
    if (newMethod == null) {
      throw new IllegalArgumentException("There is no method blubb. Have you forget to create the delegate method");
    }

    return newMethod.invoke(joinPoint.getTarget(), args);
  }

Upvotes: 1

Views: 2107

Answers (1)

R.G
R.G

Reputation: 7141

Following code would provide a handle to the annotation and the target bean (for example , here TestComponent)

A call to the TestComponent.getBar() annotated with @Example would be intercepted and advised.

@Aspect
@Component
public class ExampleAspect {

    @Around("@annotation(example) && target(bean)")
    public Object test(final ProceedingJoinPoint joinPoint,Example example,TestComponent bean) throws Throwable {
        String value = String.valueOf(example.value());
        Bar bar = convertToBar(value);
        bean.getBar(bar);
        return joinPoint.proceed();
    }
}

Do go through Spring AOP documentation : Passing Parameters to Advice for more details.

Note : For better performance it is a good idea to limit the scope of the expression as follows.

@Around("@annotation(example) && within(com.xyz.service..*) && target(bean)")

where com.xyz.service..* will limit the expression scope only to the beans with in the package com.xyz.service..* and its sub-packages.

Upvotes: 1

Related Questions