Java dynamic proxy and cglib dynamic proxy examples are Shared

  • 2020-04-01 03:12:51
  • OfStack

There are two types of Java dynamic proxy classes.

Static proxy: source code is automatically generated and compiled by a programmer or by a specific tool. The.class file for the proxy class exists before the program runs.

Dynamic proxy: created dynamically using reflection while the program is running.


First, let's demonstrate Java dynamic proxy.

Now we have a simple business interface, Saying, as follows:


package testAOP;
public interface Saying {
public void sayHello(String name);    
public void talking(String name);
}

A simple implementation class SayingImpl, as follows:


package testAOP;
public class SayingImpl implements Saying {
    @Override
    public void sayHello(String name) {
        // TODO Auto-generated method stub
        System.out.println(name + " : hello everyone! ");
    }
    @Override
    public void talking(String name) {
        // TODO Auto-generated method stub
        System.out.println(name + " I mean, we should try our best to build a harmonious society! ");
    }
}

What we're going to do is we're going to dynamically implant before and after sayHello and talking.

JDK dynamic Proxy mainly USES two classes in the java.lang.reflect package: Proxy and InvocationHandler.

The InvocationHandler is an interface that dynamically wearies together crosscutting logic and business logic by implementing an interface that defines crosscutting logic and invokes the target class's code through a reflection mechanism.

Proxy USES the InvocationHandler to dynamically create an instance that conforms to an interface and generates a Proxy object for the target class.

Here, we create an InvocationHandler instance:


package testAOP;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
    private Object target;
    MyInvocationHandler(Object target){
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        //Target method before execution
        System.out.println(" -- -- -- -- -- -- -- -- -- -- -- -- -- ");
        System.out.println(" Please take the floor next! ");
        //Target method call
        Object obj = method.invoke(target, args);
        //Target method after execution
        System.out.println(" Everyone applaud! ");
        return obj;
    }
}

Here's the test:


package testAOP;
import java.lang.reflect.Proxy;
public class JDKProxyTest {

    public static void main(String[] args) {
        //The target business class that you want to be proxied to
        Saying target = new SayingImpl();
        //Weave the target and crosscutting classes together
        MyInvocationHandler handler = new MyInvocationHandler(target);
        //Create a proxy instance
        Saying proxy = (Saying) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),//The class loader for the target class
                target.getClass().getInterfaces(),//The interface of the target class
                handler);//Crosscutting class
        proxy.sayHello(" Xiao Ming ");
        proxy.talking(" Small beautiful ");
    }
}

The operation is as follows:


 -- -- -- -- -- -- -- -- -- -- -- -- -- 
 Please take the floor next! 
 Xiaoming: hello everyone! 
 Everyone applaud! 
 -- -- -- -- -- -- -- -- -- -- -- -- -- 
 Please take the floor next! 
 Xiao li: I mean, we should try our best to build a harmonious society! 
 Everyone applaud! 

One big limitation of using JDK dynamic proxy is that it requires the target class to implement the corresponding method's interface, and it can only create proxy instances for the interface. As you can see from the newProxyInstance method of the Proxy in the test class above, the second parameter of this method is the interface of the target class. If the class does not implement an interface, it is up to the cglib dynamic proxy.

CGLib USES a very low-level bytecode technique that allows you to create a subclass for a class, and in the subclass use the technique of method interception to intercept all calls to the parent class's methods, and then populate the crosscutting logic along the way.

Next, we will demonstrate the cglib dynamic proxy.

First we need the guide package, which I used is cglib-nodep-2.1_3.jar.

Let's first create a proxy creator CglibProxy:


package testAOP.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
    Enhancer enhancer = new Enhancer();
    public Object getProxy(Class clazz) {
        //Set the subclass you want to create
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        //Subclass instances are created dynamically by bytecode techniques
        return enhancer.create();
    }
    @Override
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println(" -- -- -- -- -- -- -- -- -- -- -- -- -- ");
        System.out.println(" Please take the floor next! ");
        //Target method call
        Object result = proxy.invokeSuper(obj, args);
        //Target method after execution
        System.out.println(" Everyone applaud! ");
        return result;
    }    
}

Then test:


package testAOP.cglib;
import testAOP.Saying;
import testAOP.SayingImpl;
public class CglibProxyTest {
    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();
        //Create proxy classes by subclassing them dynamically
        Saying target = (Saying) proxy.getProxy(SayingImpl.class);
        target.sayHello(" Xiao Ming ");
        target.talking(" Small beautiful ");
    }
}

The result is no different from JDK dynamic proxies.

Both JDK dynamic proxy and CGLib dynamic proxy are runtime enhancements, enhanced by embedding cross-cutting code into proxy classes. Unlike AspectJ, which has the ability to embed crosscutting code with enhancements at compile time through a special compiler, such enhancements are more advantageous at run time because JDK dynamic proxies and CGLib dynamic proxies require enhancements every time they are run.


Related articles: