This article is participating in “Java Theme Month – Java Debug Notes Event”, see < Event link > for more details.

How do I get the underlying type of a proxy object in Java?

I want to access the class name of the base class, which is an instance of java.lang.Reflect.proxy.

Is that possible?

Answer a

You can call the proxy. GetInvocationHandler (proxy) to obtain the InvocationHandler create proxies

Note that in the case of java.lang.reflect.proxy without the underlying class itself, the Proxy is defined as follows:

  • interface
  • Call handler

Wrapped classes are usually passed to concrete invocation handlers.

Answer two

I found a great way to do this

@SuppressWarnings({"unchecked"})
protected <T> T getTargetObject(Object proxy, Class<T> targetClass) throws Exception {
  if (AopUtils.isJdkDynamicProxy(proxy)) {
    return (T) ((Advised)proxy).getTargetSource().getTarget();
  } else {
    return (T) proxy; // expected to be cglib proxy then, which is simply a specialized class}}Copy the code

Call way

@Override
protected void onSetUp(a) throws Exception {
  getTargetObject(fooBean, FooBeanImpl.class).setBarRepository(new MyStubBarRepository());
}
Copy the code

Answer three

Here is the solution my team used together (we need the name of the class after the proxy) :

if(getTargetName(yourBean) ... ) {}Copy the code
private String getTargetName(final Object target) {

    if (target == null) {
        return "";
    }

    if (targetClassIsProxied(target)) {

        Advised advised = (Advised) target;

        try {

            return advised.getTargetSource().getTarget().getClass().getCanonicalName();
        } catch (Exception e) {

            return ""; }}return target.getClass().getCanonicalName();
}

private boolean targetClassIsProxied(final Object target) {

    return target.getClass().getCanonicalName().contains("$Proxy");
}
Copy the code

Answer four

First, java.lang.reflect.Proxy only works on interfaces. The framework will create a subclass that implements the interface but extends java.lang.Reflect.Proxy rather than the application classes you might be interested in. There is no inheritance of multiple classes in Java.

Here’s my example

    Object handler = Proxy.getInvocationHandler(somethingProxied);
    Class handlerClass = handler.getClass();
    Field objField = handlerClass.getDeclaredField("obj");
    objField.setAccessible(true);
    Object behindProxy = objField.get(handler);
Copy the code

You must catch two exceptions: NoSuchFieldException and IllegalAccess sexception.

I find it useful to print the list of fields declared in the catch () clause:

. }catch (NoSuchFieldException nsfe) {
    nsfe.printStackTrace();

    Object handler = Proxy.getInvocationHandler(somethingProxied);
    Class handlerClass = handler.getClass();
    for (Field f : handlerClass.getDeclaredFields()) {
        f.setAccessible(true);
        String classAndValue = null;
        try {
            Object v = f.get(handler);
            classAndValue= "" + (v == null ? "" : v.getClass()) + ":" + v;
        } catch (IllegalAccessException iae) {
            iae.printStackTrace();
        }
        System.out.println(" field: " + f.getName() + "=" + classAndValue+ ";"); }... }Copy the code

Note that different frameworks use different agents, and even different agent technologies. A solution that works for me might not work for you (it certainly doesn’t work for Javassist or Hibernate proxies.)

The article translated from Stack Overflow:stackoverflow.com/questions/3…