The difference between dynamic agent jdk and cglib

The description of dynamic agents has been partially described in the previous two articles Detailed interpretation of dynamic agent and A simple description of dynamic agent , the dynamic proxy of JDK can only generate the proxy for the class that implements the interface. The dynamic proxy of cglib is to implement the proxy for the class, which we can use flexibly. We interpret these two kinds of dynamic agents through the example of car running.

1, JDK dynamic agent

Car interface

package proxy;

public interface Car {

    public void run();
}

Car implementation class

package proxy;

public class CarImpl implements Car{

    public void run() {
        System.out.println("car running");
    }

}

Car agent class

package proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//JDK dynamic agent class 
public class CarHandler implements InvocationHandler{
    //Object of real class
    private Object car;
    //Constructor assigned to real class
    public CarHandler(Object obj){
        this.car = obj;
    }
//When a proxy class executes a method, it calls this method
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object res = method.invoke(car, args);
        System.out.println("after");
        return res;
    }
}

main method

package proxy;

import java.lang.reflect.Proxy;

public class main {

    public static void main(String[] args) {
        CarImpl carImpl = new CarImpl();
        CarHandler carHandler = new CarHandler(carImpl);
        Car proxy = (Car)Proxy.newProxyInstance(
                main.class.getClassLoader(), //First parameter, get ClassLoader
                carImpl.getClass().getInterfaces(), //The second parameter, get the interface of the proxy class
                carHandler);//The third parameter, an InvocationHandler object, indicates which InvocationHandler object my dynamic proxy object will be associated with when I call a method
        proxy.run();
    }
}

Operation results

before
car running
after

Through the three parameters in the above example, we can see that the dynamic proxy of JDK depends on the interface. The input parameter must have the interface of the proxied class, that is, carImpl.getClass().getInterfaces(). If some classes do not implement the interface, the JDK proxy cannot be used, which requires the use of cglib dynamic proxy.

2, Cglib dynamic agent

Car without interface

package proxy;

public class CarNoInterface {

    public void run() {
        System.out.println("car running");
    }
}

cglib proxy class

package proxy;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor{

    private Object car;
    
    /** 
     * Create proxy object 
     *  
     * @param target 
     * @return 
     */  
    public Object getInstance(Object object) {  
        this.car = object;  
        Enhancer enhancer = new Enhancer();  
        enhancer.setSuperclass(this.car.getClass());  
        // Callback method  
        enhancer.setCallback(this);  
        // Create proxy object  
        return enhancer.create();  
    }  
    
    @Override
    public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {
        System.out.println("The beginning of things");  
        proxy.invokeSuper(obj, args);  
        System.out.println("The end of things");  
        return null;  
    }

}

main method

package proxy;

import java.lang.reflect.Proxy;

public class main {

    public static void main(String[] args) {    
        CglibProxy cglibProxy = new CglibProxy();
        CarNoInterface carNoInterface = (CarNoInterface)cglibProxy.getInstance(new CarNoInterface());
        carNoInterface.run();
    }
}

Result output

The beginning of things
car running
 The end of things

In the above two examples, we have seen the division of labor between the two dynamic agents. In the actual development, we can flexibly arrange whether to use interfaces or classes to proxy according to the needs.

Tags: JDK Java

Posted on Mon, 04 May 2020 07:48:58 -0400 by Jr0x