JDK 动态代理与 CGLIB 有哪些区别?

本文已参与掘金创作者训练营第三期「话题写作」赛道,详情查看:掘力计划|创作者训练营第三期正在进行,「写」出个人影响力

Spring的AOP动态代理有两种实现方式,JDK实现和CGLIB实现,那么两者有何种区别呢?

区别

JDK的动态代理主要是实现接口的方式,CGLIB主要是通过创建子类的方式,在父类的方法外进行操作。

  • 如果类是接口的时候或者类是JDK创建的proxy类时使用的是JDK代理的
  • 非接口类使用CGLib代理,或者配置注解中proxyTargetClass = true

两者的性能对比: image.png

核心代码位置

image.png

JDK动态代理原理

JDK动态代理主要是通过,反射包中的Porxy类和InvokationHandler接口。它们结合在一起后可以创建动态代理类。Porxy类基于传递的参数创建动态代理类。InvokationHandler则用于激发动态代理类的方法。这个过程是在程序执行过程中动态生成与处理的,所以叫动态代理。

代码如下:

Porxy类

Porxy类提供了一个静态方法创建动态代理类。

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

1、ClassLoader:ClassLoader会定义动态代理类,ClassLoader可以通过类或者接口获得,如果我们想通过接口获得,调用方法如下。

	Task.class.getClassLoader()
复制代码

如果通过类来获得,加入我们有一个类TaskImpl实现了Task接口,我们有个TaskImpl的对象ob,然后ClassLoader获取方法如下

	ob.getClassLoader()
复制代码

2、 Class<?>[] interfaces:动态代理类需要实现的接口

3、InvocationHandler:传递一个实现了InvokationHandler接口的类的实例

InvokationHandler

InvokationHandler是Java 反射包里面的一个接口。InvokationHandler通过用户类来实现,来激发一个动态代理类的方法。它只有一个方法:

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

1、Object:实现方法的代理对象 2、Method:代理实例激发的方法,Porxy参数中的接口方法 3、Object[]:传递给方法的一系列参数

实现

1、我们提供一个接口

package me.aihe;

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

复制代码

2、实现这个接口

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、定义自己的InvokationHandler类,并且实现InvokationHandler接口的Invoke方法

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、创建一个工厂类获取动态代理类:

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、提供我们的测试类

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));
    }
}

复制代码

看到程序的输出结果:

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

CGLIB代码案例

这里提供下使用方式。

1. 创建业务类

引入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. 实现MethodInterceptor接口

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. 动态代理

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. 输出

image.png

猜你喜欢

转载自juejin.im/post/6997416275492208648