美文网首页
JDK提供的动态代理和Cglib技术

JDK提供的动态代理和Cglib技术

作者: 耐得千事烦 | 来源:发表于2019-08-14 14:58 被阅读0次

前言

本篇文章主要是起到过渡作用的。我们都知道springAOP的实现底层是靠JDK提供的接口动态代理和Cglib字节码增强技术来实现的,那么我们这篇文章主要就是说说到底如何使用编程的方式来用这俩个实现动态代理。

JDK的接口动态代理

直接看代码吧:
先定义一个Children接口:

package com.suxin.dynamicProxyAndCglib.jdk;

public interface Children {
    void eat();
    void sleep();
}

定义Alice,用来实现了Children接口

package com.suxin.dynamicProxyAndCglib.jdk;

//alice是一个小孩子
public class Alice implements Children{
    //需要增强这个方法,在吃东西前需要先洗手,吃完东西需要刷牙
    public void eat() {
        System.out.println("吃东西");
    }
    public void sleep() {
        System.out.println("睡觉了");
    }
}

再定义一个ChildrenInvocationHandler,用来实现InvocationHandler接口

package com.suxin.dynamicProxyAndCglib.jdk;

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

public class ChildrenInvocationHandler implements InvocationHandler {
    //实际对象
    private Object children;
    //构造方法
    public ChildrenInvocationHandler(Object children) {
        this.children = children;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //只对eat方法进行了增强
        if(method.getName().equals("eat")) {
            System.out.println("先洗手");
            method.invoke(children,args);
            System.out.println("吃完了,现在要刷牙");
        }else {
            //不是eat方法则还是原先的业务逻辑不做方法增强
            method.invoke(children,args);
        }
        return null;
    }
}

客户端main方法:

package com.suxin.dynamicProxyAndCglib.jdk;

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

public class Clinet {
    public static void main(String[] args) {
        Alice alice = new Alice();
        //把目标对象存进去
        InvocationHandler handler = new ChildrenInvocationHandler(alice);
        //InvocationHandler的class对象,通过它来获取类加载器
        Class clazz = handler.getClass();
        ClassLoader classLoader = clazz.getClassLoader();

        //获取alice实现的接口class对象的数组
        Class[] interfaceClasses = alice.getClass().getInterfaces();
        //创建实现了Children接口的代理对象
        Children childrenProxy = (Children)Proxy.newProxyInstance(classLoader, interfaceClasses, handler);
        childrenProxy.eat();//执行吃方法
        childrenProxy.sleep();//执行睡觉方法
    }
}

直接看控制台打印输出:

先洗手
吃东西
吃完了,现在要刷牙
睡觉了

可以看到通过JDK提供的InvocationHandler和Proxy类我们实现了动态代理。

优点:不依赖第三方jar包, 使用方便;随着JDK的升级,JDK动态代理的性能在稳步提升
缺点:只适用于实现了接口类;执行速度较慢


CGLib

CGLib(代码生成库)主要用于生成类代理。这是通过在运行时创建子类来实现的,其中方法调用被用户定义的方法拦截。另外,cglib提供了不同的扩展,例如bean实用程序。cglib构建于ASM之上

来自于stackoverflow上对cglib的解释

使用前
需要在项目中依赖cglib相关的jar包和asm jar包。因为SpringCore部分已经集成了cglib相关的源码了,所以我直接用的是spring框架。
上代码:

package com.suxin.dynamicProxyAndCglib.cglib;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {

    private Enhancer enhancer = new Enhancer();
    /**
     *获取代理对象
     */
    public Object getProxy(Class clazz) {
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    /**
     *实现 MethodInterceptor接口方法
     */
    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object result;
        if(method.getName().equals("eat")) {
            System.out.println("先洗手");
            result = methodProxy.invokeSuper(object,args);
            System.out.println("吃完了,现在要刷牙");
        }else {
            result = methodProxy.invokeSuper(object,args);
        }
        return result;
    }
}

client的main方法进行运行

package com.suxin.dynamicProxyAndCglib.cglib;

import com.suxin.dynamicProxyAndCglib.jdk.Alice;

public class Client {
    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        Alice alice = (Alice)cglibProxy.getProxy(Alice.class);
        alice.eat();
        alice.sleep();
    }
}

给出控制台打印:

先洗手
吃东西
吃完了,现在要刷牙
睡觉了

优点:可以代理没有实现接口的对象;由于是动态生成字节码实现代理,因此代理对象的执行速度较快。
缺点:动态生成字节码虽然执行较快,但是生成速度很慢。

以上就是JDK动态代理和CGLib技术的使用demo,学习以后我们接下来就是学习Spring的AOP的源码了

相关文章

  • JDK动态代理和CGLIB动态代理的区别

    Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理: JDK动态代理只提供接口的代...

  • JDK和CGLIB动态代理区别

    JDK和CGLIB动态代理区别 一 JDK和CGLIB动态代理原理1、JDK动态代理利用拦截器(拦截器必须实现In...

  • Java面试之Java基础下册(含答案)

    15.动态代理与cglib实现的区别。 动态代理有两种实现方式,分别是:jdk动态代理和cglib动态代理 jdk...

  • Java 代理

    静态代理 动态代理 JDK 提供的Proxy CGLib cglib | GitHub 参考文章 Java的三种代理模式

  • 源码解析--JDK动态代理

    动态代理的两种方式JDK动态代理和cglib动态代理在上一篇中动态代理jdk和cglib的区别已经通过实例做了比较...

  • 面试系列~动态代理实现与原理

    动态代理有JDK动态代理, CGLIB动态代理, SpringAOP动态代理 一,JDK动态代理  jdk动态代理...

  • java动态代理

    目录: 简介 jdk动态代理 cglib动态代理 jdk动态代理与cglib的区别 应用spring的aop 简介...

  • 保存java 动态代理生成的字节码文件

    保存java 动态代理生成的字节码文件 在Java中,常用的动态代理技术有JDK的动态代理和cglib动态代理,不...

  • Cglib和jdk动态代理

    Cglib和jdk动态代理说到cglib技术,使用的就是增强类Enhancer,底层使用的ASM技术.下面举例说明...

  • Spring的AOP原理分析

    一 动态代理 动态代理分为JDK动态代理和CGLIB动态代理 jdk动态代理 被代理类(目标类)和代理类必须实现同...

网友评论

      本文标题:JDK提供的动态代理和Cglib技术

      本文链接:https://www.haomeiwen.com/subject/eexgjctx.html