JDK 代理和 CGLib 有什么区别?

JDK 代理和 CGLib 有什么区别?

动态代理是一种机制,程序通过该机制在运行时动态生成代理对象并调用代理方法。动态代理主要有两种实现机制,一种是基于反射动态代理的JDK,另一种是基于ASM动态代理机制的CGLib实现。现在让我们谈谈两种实现之间的区别以及如何实现它们

JDK 代理和 CGLib 之间的区别

  • JDK动态代理采用反射机制实现,而CGLib基于ASM机制实现,性能不同

  • JDK动态代理是Java语言的内置功能,它不断更新和升级,没有任何维护问题。CGLib是基于第三方工具实现的,两种实现方式往往不同。

  • JDK动态代理必须通过接口实现,调用起来相对简单,而CGLib不需要接口,调用起来相对复杂。

JDKProxy 动态代理实现

JDK 动态代理通过反射类代理和 InvocationHandler 接口实现。由于JDK中的所有动态代理类都必须实现一个接口,也就是说,动态代理类必须实现在动态代理接口中定义的方法,这会导致反射效率低。

  • 代码实现
public class JdkTokProxyT 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

从上面的代码中可以看出,JDK 动态代理使用 Proxy 类中的 newProxyInstance 方法创建一个动态代理对象。

newProxyInstance 方法主要采用

参数描述
类加载器加载器 当前用于装入代理对象的字节码的类装入器。使用与代理对象相同的类装入器。固定写入
类?[] 接口 当前由可执行对象实现的所有接口的字节码数组,用于使可执行对象和可执行对象具有相同的方法。固定写入
InvocationHandler h 目前,当代理对象执行目标方法时,我们可以使用 H 定义拦截增强方法,即我们编写如何代理。我们通常为此接口编写一个实现类,通常是匿名内部类,但这不是必需的。

invoke 方法的主要功能是通过执行支撑对象的任何接口方法传递,或者更确切地说,一个侦听方法,即调用 main 方法参数

参数描述
代理 对代理对象的引用
方法 当前执行的方法
参数 当前执行方法所需的参数
返回 具有与代理对象相同的返回值

invoke() 方法是 JDK 代理的调用接口,它使用 Invocation Invo Invocation。

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

这是因为在动态代理中有一个重要作用,即代理,它用于集中管理prostedobject。显然,InvoHandler 就是这个代理,invoke() 方法是触发代理的执行方法。我们通过实现调用接口来获得动态代理功能。

实施附加

如果使用由 CGLib 实现的动态代理,则不需要代理类来实现接口,这提高了性能,因为 CGLib 使用下面的 ASM 框架,该框架通过字节码技术生成代理类。

动态生成一个支持子类,该子类覆盖支持类的所有非最终方法。方法拦截拦截子类中对父方法的所有调用,将横切逻辑编织到子类中,这比Java的反射JDK动态代理更快.

Cglib 是一个功能强大、高性能的代码生成包,在许多 AOP 框架中广泛用于提供方法拦截

  • 代码实现如下
    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

    从上面的代码中可以看出,CGLib 是基于子类实现的动态代理,并使用增强器类中的 create 方法创建代理对象。因此,代理类不能由关键字 final 修改。如果由 final 修改,则在使用增强器设置父类时将报告错误,并且无法构建动态代理。

热门相关:英雄联盟之巅峰王座   沉迷按摩的准新娘   网游三国之城市攻略   异能特工:军火皇后   我是仙凡