JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

jdk动态代理和cglib动态代理的区别

wys521 2024-12-30 07:36:21 精选教程 24 ℃ 0 评论

JDK动态代理主要是基于Java标准库中的java.lang.reflect.Proxy类来实现,通过在运行时生成实现了特定接口的类来实现动态代理操作。它有个硬性的要求就是被代理类必须实现一个或多个接口,否则就无法使用JDK的动态代理,调用相应的方法会报错。

CGLIB(Code Generation Library)动态代理是基于第三方库来实现的,通过在运行时生成目标类的子类,然后在在子类中覆盖目标类的方法来实现动态代理操作的。这种方式并不需要要求一定要实现某个接口。既然是覆盖目标类的方法,那么就要求目标类不能为final 类,否则就无法生成子类进行代理操作,并且还要求目标类的方法也不能是final,否则就无法实现方法覆盖。

从介绍中可知,两种代理方法都是要生成新类,只不过是一种基于被代理类的接口,一种基于被代理类,而且用于生成新类字节码的类库不同。

我们先来看看他们的相同点和不同点,然后再用实例介绍。

相同点:

1、两种动态代理方法都是按照java的字节码文件格式也就是class文件格式生成新的字节码,即数据字节流,然后读入到JVM创建class对象,再用反射API创建新类的实例对象。

2、从生成的字节码文件可以看出,他们都重写了父类的方法,并且每个方法的方法体主要内容就是调用代理类的拦截方法,只是他们各自的拦截方法名称不同。

3、代理类想要额外增加的功能逻辑都在拦截方法中,而且他们都是通过反射API来执行被代理类的方法。


不同点:

1、生成字节码采用的类库不同。JDK动态代理是使用jdk运行时包里的ProxyGenerator类来生成字节码文件内容;CGLIB动态代理是使用ASM类库里的各种类来组织生成字节码文件内容。

2、在生成新类的方法时,方法的来源不同。JDK动态代理是通过反射API读取被代理类的接口的方法,来组织生成新类的方法;而CGLIB动态代理是通过反射API读取被代理类及其接口的方法,来组织生成新类的方法。所以,如果被代理类没有实现任何一个接口,或者接口里没有任何方法,那么新生成的类就不会有和被代理类里一样的方法。

3、新类的类名命名规则不同。JDK动态代理生成的新类的类名是以$Proxy开头的,后面跟的是从0开头的数字,每创建一个新类,数字递增;CGLIB动态代理生成的新类的类名是以被代理类的类名开头,接着是固定的字符串$EnhancerByCGLIB$,最后面的是一些关键字的hashcode值转换成十六进制后的字符串;

4、传递代理类对象给新类对象的方式不同。新类的对象要调用代理类的拦截方法,那新类对象肯定要知道代理类对象,JDK动态代理的实现方式是在创建新类对象时将代理类对象传递给构造函数,构造函数将它保存在一个实例属性中;而CGLIB动态代理的实现方式是在新类读入JVM后,调用新类的静态方法将代理类的对象保存在一个静态属性中。

5、新类和被代理类的关系不同。JDK动态代理生成的新类和被代理类一样,都是实现同一个接口,它们是平等的兄弟关系;而CGLIB动态代理生成的新类是继承被代理类的,和被代理类是父子关系。


jdk动态代理例子

实体类User

public class User {

    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}


被代理类的接口

import java.util.List;

public interface UserService {
    List<User> getUserList();

    void addUser();
}

被代理类

import java.util.Collections;
import java.util.List;

public class UserServiceImpl implements UserService {

    @Override
    public List<User> getUserList() {
        return Collections.singletonList(new User("pdai", 18));
    }

    @Override
    public void addUser() {
        // do something
    }
}


代理类

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

public class LogProxy<T> implements InvocationHandler {
    //代理对象
    private T target;

    public <B extends T> T getInstance(B target){
        this.target = target;
        Class clazz = this.target.getClass();
        // 参数1:被代理类的类加载器 参数2:被代理类的接口 参数3:代理类对象
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // log - before method
        System.out.println("[before] execute method: " + method.getName());

        Object result = method.invoke(target,args);

        // log - after method
        System.out.println("[after] execute method: " + method.getName() + ", return value: " + result);

        return null;
    }
}


主类

import sun.misc.ProxyGenerator;
import java.io.FileOutputStream;

public class ProxyMain {
    public static void main(String[] args) throws Exception {
        //生成代理对象
        UserServiceImpl proxy =  new LogProxy<UserServiceImpl>().getInstance(new UserServiceImpl());

        // call methods
        proxy.getUserList();
        proxy.addUser();

        // 将jdk生成的代理类输出了出来,方便后面分析使用
        byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0",new Class[]{ProductService.class});
        FileOutputStream os = new FileOutputStream("Proxy0.class");
        os.write(bytes);
        os.close();

    }

}


生成的类文件

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.List;

public final class $Proxy0 extends Proxy implements UserService {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;
    private static Method m4;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final List getUserList() throws  {
        try {
            return (List)super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void addUser() throws  {
        try {
            super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.feng.proxytest.jdk.UserService").getMethod("getUserList");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m4 = Class.forName("com.feng.proxytest.jdk.UserService").getMethod("addUser");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}


cglib动态代理

实体实User和上面的一样。

被代理类

import java.util.Collections;
import java.util.List;

public class UserServiceImpl {

    public List<User> findUserList() {
        return Collections.singletonList(new User("pdai", 18));
    }

    public void addUser() {
        // do something
    }

}


代理类

import java.lang.reflect.Method;
import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class LogProxy implements MethodInterceptor {

    /**
     * 业务类对象,供代理方法中进行真正的业务方法调用
     */
    private Object target;

    public Object getUserLogProxy(Object target) {
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\cglib");

        //给业务对象赋值
        this.target = target;
        //创建加强器,用来创建动态代理类
        Enhancer enhancer = new Enhancer();
        //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
        enhancer.setSuperclass(this.target.getClass());
        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
        enhancer.setCallback(this);
        // 创建动态代理类对象并返回
        return enhancer.create();
    }

    // 实现回调方法
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // log - before method
        System.out.println("[before] execute method: " + method.getName());

        // call method
        Object result = proxy.invokeSuper(obj, args);

        // log - after method
        System.out.println("[after] execute method: " + method.getName() + ", return value: " + result);
        return null;
    }
}


主类

public class ProxyMain {

    public static void main(String[] args) {
        // 生成代理对象
        UserServiceImpl userService = (UserServiceImpl) new LogProxy().getUserLogProxy(new UserServiceImpl());

        // call methods
        userService.findUserList();
        userService.addUser();
    }
}


生成的类文件

import java.lang.reflect.Method;
import java.util.List;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class UserServiceImpl$EnhancerByCGLIB$adb16b85 extends UserServiceImpl implements Factory {
    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    private MethodInterceptor CGLIB$CALLBACK_0;
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$findUserList$0$Method;
    private static final MethodProxy CGLIB$findUserList$0$Proxy;
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$addUser$1$Method;
    private static final MethodProxy CGLIB$addUser$1$Proxy;
    private static final Method CGLIB$equals$2$Method;
    private static final MethodProxy CGLIB$equals$2$Proxy;
    private static final Method CGLIB$toString$3$Method;
    private static final MethodProxy CGLIB$toString$3$Proxy;
    private static final Method CGLIB$hashCode$4$Method;
    private static final MethodProxy CGLIB$hashCode$4$Proxy;
    private static final Method CGLIB$clone$5$Method;
    private static final MethodProxy CGLIB$clone$5$Proxy;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("com.feng.proxytest.cglib.UserServiceImpl$EnhancerByCGLIB$adb16b85");
        Class var1;
        Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
        CGLIB$equals$2$Method = var10000[0];
        CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
        CGLIB$toString$3$Method = var10000[1];
        CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
        CGLIB$hashCode$4$Method = var10000[2];
        CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
        CGLIB$clone$5$Method = var10000[3];
        CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
        var10000 = ReflectUtils.findMethods(new String[]{"findUserList", "()Ljava/util/List;", "addUser", "()V"}, (var1 = Class.forName("com.feng.proxytest.cglib.UserServiceImpl")).getDeclaredMethods());
        CGLIB$findUserList$0$Method = var10000[0];
        CGLIB$findUserList$0$Proxy = MethodProxy.create(var1, var0, "()Ljava/util/List;", "findUserList", "CGLIB$findUserList$0");
        CGLIB$addUser$1$Method = var10000[1];
        CGLIB$addUser$1$Proxy = MethodProxy.create(var1, var0, "()V", "addUser", "CGLIB$addUser$1");
    }

    final List CGLIB$findUserList$0() {
        return super.findUserList();
    }

    public final List findUserList() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (List)var10000.intercept(this, CGLIB$findUserList$0$Method, CGLIB$emptyArgs, CGLIB$findUserList$0$Proxy) : super.findUserList();
    }

    final void CGLIB$addUser$1() {
        super.addUser();
    }

    public final void addUser() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$addUser$1$Method, CGLIB$emptyArgs, CGLIB$addUser$1$Proxy);
        } else {
            super.addUser();
        }
    }

    final boolean CGLIB$equals$2(Object var1) {
        return super.equals(var1);
    }

    public final boolean equals(Object var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var2 = var10000.intercept(this, CGLIB$equals$2$Method, new Object[]{var1}, CGLIB$equals$2$Proxy);
            return var2 == null ? false : (Boolean)var2;
        } else {
            return super.equals(var1);
        }
    }

    final String CGLIB$toString$3() {
        return super.toString();
    }

    public final String toString() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy) : super.toString();
    }

    final int CGLIB$hashCode$4() {
        return super.hashCode();
    }

    public final int hashCode() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var1 = var10000.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
            return var1 == null ? 0 : ((Number)var1).intValue();
        } else {
            return super.hashCode();
        }
    }

//部分代码有省略........

    public UserServiceImpl$EnhancerByCGLIB$adb16b85() {
        CGLIB$BIND_CALLBACKS(this);
    }

    public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
        CGLIB$THREAD_CALLBACKS.set(var0);
    }

    public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
        CGLIB$STATIC_CALLBACKS = var0;
    }

    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
        UserServiceImpl$EnhancerByCGLIB$adb16b85 var1 = (UserServiceImpl$EnhancerByCGLIB$adb16b85)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (var10000 == null) {
                    return;
                }
            }

            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }

    }

    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        UserServiceImpl$EnhancerByCGLIB$adb16b85 var10000 = new UserServiceImpl$EnhancerByCGLIB$adb16b85();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        UserServiceImpl$EnhancerByCGLIB$adb16b85 var10000 = new UserServiceImpl$EnhancerByCGLIB$adb16b85();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        UserServiceImpl$EnhancerByCGLIB$adb16b85 var10000 = new UserServiceImpl$EnhancerByCGLIB$adb16b85;
        switch(var1.length) {
        case 0:
            var10000.<init>();
            CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
            return var10000;
        default:
            throw new IllegalArgumentException("Constructor not found");
        }
    }

    public Callback getCallback(int var1) {
        CGLIB$BIND_CALLBACKS(this);
        MethodInterceptor var10000;
        switch(var1) {
        case 0:
            var10000 = this.CGLIB$CALLBACK_0;
            break;
        default:
            var10000 = null;
        }

        return var10000;
    }

    public void setCallback(int var1, Callback var2) {
        switch(var1) {
        case 0:
            this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
        default:
        }
    }

    public Callback[] getCallbacks() {
        CGLIB$BIND_CALLBACKS(this);
        return new Callback[]{this.CGLIB$CALLBACK_0};
    }

    public void setCallbacks(Callback[] var1) {
        this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
    }

    static {
        CGLIB$STATICHOOK1();
    }
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表