What is the difference between JDK dynamic proxy and CGLIB?

This article has participated in the third "topic writing" track of the Nuggets creator training camp. For details, please refer to: Digging Power Plan | The third phase of the creator training camp is in progress, "writing" to show personal influence .

Spring's AOP dynamic proxy has two implementations, JDK implementation and CGLIB implementation, so what is the difference between the two?

the difference

The dynamic proxy of JDK is mainly to implement the interface, and CGLIB mainly operates outside the method of the parent class by creating subclasses.

  • If the class is an interface or the class is a proxy class created by JDK, the JDK proxy is used
  • Use CGLib proxy for non-interface classes, or proxyTargetClass = true in configuration annotations

Performance comparison of the two:image.png

core code location

image.png

JDK dynamic proxy principle

The JDK dynamic proxy is mainly through the Porxy class and the InvokationHandler interface in the reflection package. Together they create dynamic proxy classes. The Porxy class creates dynamic proxy classes based on passed parameters. InvokationHandler is used to stimulate the methods of dynamic proxy classes. This process is dynamically generated and processed during program execution, so it is called dynamic proxy.

code show as below:

Porxy class

The Porxy class provides a static method to create dynamic proxy classes.

public static Object newProxyInstance(ClassLoader loader,           
    Class<?>[] interfaces,                                      
    InvocationHandler h)
throws IllegalArgumentException
复制代码

1. ClassLoader: ClassLoader will define a dynamic proxy class. ClassLoader can be obtained through a class or interface. If we want to obtain it through an interface, the calling method is as follows.

	Task.class.getClassLoader()
复制代码

If we get it through a class, add that we have a class TaskImpl that implements the Task interface, we have an object ob of TaskImpl, and then the ClassLoader gets the method as follows

	ob.getClassLoader()
复制代码

2. Class<?>[] interfaces: the interface that the dynamic proxy class needs to implement

3. InvocationHandler: Pass an instance of a class that implements the InvokationHandler interface

InvokationHandler

InvokationHandler is an interface in the Java reflection package. The InvokationHandler is implemented by the user class to trigger the methods of a dynamic proxy class. It has only one method:

public Object invoke(Object proxy, Method method, Object[] args)    throws Throwable;
复制代码

1. Object: The proxy object that implements the method 2. Method: The method excited by the proxy instance, the interface method in the Porxy parameter 3. Object[]: A series of parameters passed to the method

accomplish

1. We provide an interface

package me.aihe;

public interface Task {
    void setData(String data);
    int getCalData(int x);
}

复制代码

2. Implement this interface

package me.aihe;

public class TaskImpl implements Task {
    @Override
    public void setData(String data) {
        System.out.println(data+ " Data is saved");
    }

    @Override
    public int getCalData(int x) {
        return x * 10;
    }
}

复制代码

3. Define your own InvokationHandler class and implement the Invoke method of the InvokationHandler interface

package me.aihe;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MyInvokationHandler implements InvocationHandler {

    private Object obj;
    public MyInvokationHandler(Object object){
        this.obj = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result;
        if(method.getName().contains("get")){
            System.out.println("...get Method Executing...");
        }else{
            System.out.println("...set Method Executing...");
        }
        result = method.invoke(obj, args);
        return result;
    }
}

复制代码

4. Create a factory class to get the dynamic proxy class:

package me.aihe;

import java.lang.reflect.Proxy;

public class ProxyFactory {
    public static Object newInstance(Object ob) {
        return Proxy.newProxyInstance(ob.getClass().getClassLoader(),
                new Class<?>[] { Task.class }, new MyInvokationHandler(ob));
    }
}

复制代码

5. Provide our test class

package me.aihe;

public class Test {

    public static void main(String[] args) {
        Task task = (Task)ProxyFactory.newInstance(new TaskImpl());
        task.setData("Test");
        System.out.println("============");
        System.out.println(task.getCalData(5));
    }
}

复制代码

See the output of the program:

...set Method Executing...
Test Data is saved
============
...get Method Executing...
50
复制代码

CGLIB code example

Here's how to use it.

1. Create a business class

Introduce Maven:

<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

复制代码
package cglib.enhancer;
 
public class Hello {
    public String sayHello(boolean throwException) throws Exception {
        System.out.println("hello everyone!");
        if(throwException)
            throw new Exception("test exception");
        return "123";
    }
}
复制代码

2. Implement the MethodInterceptor interface

package cglib.enhancer;
 
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 ProxyFactory implements MethodInterceptor {
     //要代理的原始对象
    private Object obj;
    public Object createProxy(Object target) {
        this.obj = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.obj.getClass());// 设置代理目标
        enhancer.setCallback(this);// 设置回调
        enhancer.setClassLoader(target.getClass().getClassLoader());
        return enhancer.create();
    }
 
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        Object result = null;
        try {
            // 前置通知
            before();
            result = proxy.invokeSuper(obj, args);
            // 后置通知
            after();
        } catch (Exception e) {
            exception();
        }finally{
            beforeReturning();
        }
        return result;
    }
 
 
    private void before() {
        System.out.println("before method invoke");
    }
    private void after() {
        System.out.println("after method invoke");
    }
    private void exception() {
        System.out.println("method invoke exception");
    }
    private void beforeReturning() {
        System.out.println("before returning");
    }
}

复制代码

3. Dynamic proxy

package cglib.enhancer;
 
public class EnhancerTest {
    public static void main(String[] args) throws Exception {
        Hello hello = new Hello();
        ProxyFactory cglibProxy = new ProxyFactory();
        Hello proxy = (Hello) cglibProxy.createProxy(hello);
        String result=proxy.sayHello(true);
        System.out.println(result);
    }
}
复制代码

4. Output

image.png

Guess you like

Origin juejin.im/post/6997416275492208648