This is the 10th day of my participation in the First Challenge 2022, for more details: First Challenge 2022

What is the difference between JDK Proxy and CGLib?

Dynamic proxies are a mechanism by which a program dynamically builds proxy objects and invokes proxy methods at run time. Dynamic proxy mainly has two implementation mechanisms, one is JDK based on reflection dynamic proxy, the other is CGLib based on ASM dynamic proxy mechanism implementation. Now let’s talk about the difference between the two implementations and how to implement them

Differences between JDK Proxy and CGLib

  • JDK dynamic proxy is implemented using reflection mechanism, while CGLib is implemented based on ASM mechanism, which has different performance

  • JDK dynamic proxy is a built-in function of the Java language, and it is continuously updated and upgraded without any maintenance issues. CGLib is implemented based on third-party tools, and the two implementations are often different.

  • JDK dynamic proxies must be implemented through interfaces and are relatively simple to call, whereas CGLib does not require interfaces and is relatively complex to call.

JDKProxy dynamic proxy implementation

JDK dynamic Proxy is implemented through the reflection class Proxy and the InvocationHandler interface. Since all dynamic Proxy classes in JDK must implement an interface, that is, dynamic Proxy classes must implement methods defined in the dynamic Proxy interface to Proxy, which results in low reflection efficiency.

  • Code implementation
public class JdkTokProxy<T> implements InvocationHandler {

    private T target;

    public JdkTikTokProxy(T target) {
        this.target = target;
    }

    public static <T> T getProxy(T t) {
        Object o = Proxy.newProxyInstance(t.getClass().getClassLoader()
                , t.getClass().getInterfaces()
                , new JdkTikTokProxy(t));
        return (T) o;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // reflection executes
        System.out.println("Methods that actually execute the proxied object");
        Object invoke = method.invoke(target, args);
        System.out.println("Return value:" + invoke);
        return null; }}Copy the code

As you can see from the code above, the JDK dynamic Proxy creates a dynamic Proxy object using the newProxyInstance method in the Proxy class.

The newProxyInstance method takes mainly

parameter describe
ClassLoader loader The class loader that is currently used to load the bytecode of the proxy object. Use the same classloader as the proxied object. Fixed writing
Class<? >[] interfaces The bytecode array of all interfaces currently implemented by the proachable object, which is used to make the proachable object and the proachable object have the same methods. Fixed writing
InvocationHandler h Currently, when the proxied object executes the target method, we can define interception enhancement methods using H, which is let us write how to proxied. We usually write an implementation class for this interface, usually an anonymous inner class, but it is not required.

The invoke method’s main function is to pass through any interface method that executes a propped object, or rather, a listening method, the invoke main method argument

parameter describe
proxy A reference to a proxy object
method The method currently executed
args Parameters required by the current execution method
return Has the same return value as the proxied object

The invoke() method is the Invocation interface of the JDK Proxy, which uses the Invocation Invocation Invocation.

public interface InvocationHandler { 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; 
}
Copy the code

This is because there is an important role in the dynamic proxy, the proxy, which is used to centrally manage the prostedobject. Obviously InvocationHandler is this proxy, and the invoke() method is the execution method that triggers the proxy. We have dynamic proxy capability by implementing the Invocation interface.

The implementation of additional

If you use a dynamic proxy implemented by CGLib, you don’t need a proxy class to implement the interface, which increases performance because CGLib uses the ASM framework underneath, which generates proxy classes through bytecode technology.

Dynamically generates a propped subclass that overrides all non-final methods of the propped class. Method interception intercepts all calls to parent methods in subclasses, weaving crosscutting logic into the subclass, which is faster than Java’s reflective JDK dynamic proxy

Cglib is a powerful, high-performance code generation package that is widely used in many AOP frameworks to provide method interception

  • The code implementation is as follows
public class CglibProxy {
    public static <T> T createProxy(T t) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(t.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
   
                System.out.println("Cglib is on.");
                Object invoke = proxy.invokeSuper(obj, args);
                returninvoke; }}); Object o = enhancer.create();return(T) o; }}Copy the code

As you can see from the code above, CGLib is a dynamic proxy based on the subclass implementation and creates the proxy object by using the create method in the Enhancer class. Therefore, the proxyed class cannot be modified by the keyword final. If it is modified by final, an error will be reported when setting the parent class using Enhancer, and the dynamic proxy will fail to be built.