How to call a proxy method (Spring AOP) by reflection in Java?

Interface:

public interface Manager {
  Object read(Long id);
}

A class that implements this interface:

@Transactional
Public class ManagerImpl implements Manager {
  @Override  
  public Object read(Long id) {
    //  Implementation here  
  }
}

Aspect for ManagerImpl:

@Aspect
public class Interceptor {
  @Pointcut("execution(public * manager.impl.*.*(..))")
  public void executionAsManager() {
  }

  @Around("executionAsManager()")
  public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
    //  Do some actions
    return joinPoint.proceed();
  }
}

Controller:

@RestController()
public class Controller {

  @Autowired
  private Manager manager;

  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public Object read(@PathVariable Long id) {
    return manager.read(id);
  }

  @RequestMapping(value = "reflection/{id}", method = RequestMethod.GET)
  public Object readViaReflection(@PathVariable Long id) {
    return ManagerImpl.class.getMethod("read", Long.class).invoke(manager, id);
  }
}

So, when spring enters a control variable in the created controller proxy.
When calling the method directly:

manager.read(1L)  

called out.

However, when I try to do this (see readViaReflection )

ManagerImpl.class.getMethod("read", Long.class).invoke(manager, 1L);

received object java.lang.reflect.InvocationTargetException is not an instance of a class declaration.
It is reasonable.

The question is: how can I call a method through reflection on a proxy created by spring (I have a method extracted from the target and I have a proxy instance created by spring).

, .

+4
4

, ManagerImpl bean, beacause Bean .

, .

if (Proxy.isProxyClass(manager.getClass())) {
    Method readMethod = ManagerImpl.class.getMethod("read", Long.class);
    Proxy.getInvocationHandler(manager).invoke(manager, readMethod, parameter);
} else
    info.getMethod().invoke(serviceClass, parameter);

else , Bean -, ManagerImpl , - CGLib ( ManagerImpl ).

+1

proxy. :

manager.getClass().getMethod("read", Long.class).invoke(manager, 1L);

0

, java , if() pointcut

To implement it, you can define another boolean argument (named invokeAOP) when you call managerwith invokeAOP = true, then you get your Aspect exectued. Otherwise, your aspect will be omitted.

0
source

You can do this without using reflection - it just needs some kind of casting:

((Manager) ((Advised)manager).getTargetSource().getTarget()).read(1L);

It’s great that it works with JDK and CGLIB proxies.

If you need to use reflection, just use part of this solution:

Manager managerBean = ((Manager) ((Advised)manager).getTargetSource().getTarget()); managerBean.getClass().getMethod("read", Long.class).invoke(managerBean, id)

0
source

Source: https://habr.com/ru/post/1598701/


All Articles