Java InvocationHandler and dynamic agent Proxy Comments

Proxy class

Method newProxyInstance Proxy returns a proxy object class:

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
  • loader: a class loader, use the default class loader with null.
  • interfaces: a Class array of objects, each element needs to implement.
  • h: a call processor.

The other two methods:

  • public static Class getProxyClass (ClassLoader loader, Class ... interfaces <?>) <?>: Returns a proxy class interface.
  • public static boolean isProxyClass (Class cl <?>): If cl is a proxy class returns true.

InvocationHandler Interface

The third parameter is the InvocationHandler newProxyInstance methods, this interface is only one way:

public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;

When a call any method of the proxy class, invoke the method will be called first, method is the way the original object, args is the original parameters of the method.

Here's the first argument proxy, he is the real object (that is, we want to proxy object) of the proxy object, that object which is actually the Proxy newInstance method returns. Under normal circumstances, we are the real object method returns the result of calling the invoke () method, when we need to continuously proxy object calls (chain call), you can return the object.

General chaos under (target for the real object):

public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
    return method.invoke(target, args);
}

Require continuous call time:

public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
    method.invoke(target, args);
    return proxy;
}

Dynamic proxies simple implementation

Now, create a Hero interface, which contains an attack () method, and then use dynamic proxies, any implementation of the interface are heroes Hero print "before casting shake" and "after casting shake" before and after the call to attack.

package cloud.proxy;

public interface Hero {
    void attack();
}

Then create a cast Thunder Wrath of Zeus:

package cloud.proxy;

import static Java.lang.System.out;

public class Zues implements Hero {
    @Override
    public void attack() {
        out.println("雷神之怒!");
    }
}

Finally, create a proxy object HeroProxy categories:

package cloud.proxy;

import java.lang.reflect.Proxy;

import static java.lang.System.out;

public class HeroProxy {
    private void before() {
        out.println("准备施法...");
    }

    private void after() {
        out.println("施法完成。");
    }

    public Hero newInstance(final Class<? extends Hero> targetClass) throws Throwable {
        Hero target = targetClass.getConstructor().newInstance();
        return (Hero) Proxy.newProxyInstance(Hero.class.getClassLoader(), new Class[]{Hero.class},
                (proxy, method, args) -> {
                    before();
                    Object result = method.invoke(target, args);
                    after();
                    return result;
                }
        );
    }
}

When you call HeroProxy the newInstance () method, created the original object target, and then to get the proxy object through Proxy class, did not create this entity class implements InvocationHandler, but uses the anonymous class (lambda expression).

Test categories:

package cloud.proxy;

import org.junit.Test;

public class HeroProxyTest {

    @Test
    public void getProxyObject() throws Throwable {
        HeroProxy proxy = new HeroProxy();
        // 创建 Zues 的代理对象
        Hero hero = proxy.newInstance(Zues.class);
        hero.attack();
    }
}

Results of the:

com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit4 cloud.proxy.HeroProxyTest 

ready to cast ... 
Thunder Wrath! 
Casting is complete. 



Process finished with exit code 0

Tips

Proxy class is useful when tracking method call, for example, we can create a proxy class for the Comparable interface, before compareTo method calls, print out some information, so that you can see the process more time to sort.

Guess you like

Origin www.linuxidc.com/Linux/2019-08/160011.htm