zoukankan      html  css  js  c++  java
  • CGLib动态代理

    导入jar包

    asm-7.0.jar
    cglib-3.2.10.jar
    1
    2
    仍然以加法运算为例

    //定义目标对象的类和方法
    class CalculatorService{
    public int add(int a, int b) {
    int result = a+b;
    return result;
    }
    }

    public class ProxyFactory {
    static CalculatorService target; //目标对象
    //MethodInterceptor接口继承自Callback接口
    static Callback callback=new MethodInterceptor() {

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    //第一个参数对象是代理对象
    System.out.println(target+"111"+proxy.getClass().getName());
    return 0; //将来调用的目标方法的返回值
    }
    };


    public static Object getProxy(CalculatorService target){
    ProxyFactory.target=target;
    Enhancer enhancer=new Enhancer();
    enhancer.setSuperclass(target.getClass());
    //用CGLib的方式实现动态代理,所生成的对象对应的类,是目标对象对应的CalculatorService类的子类;jdk动态代理是同级的关系
    enhancer.setCallback(callback);
    return enhancer.create();
    }
    }

    class Test {

    public static void main(String[] args) {

    CalculatorService calculatorService = (CalculatorService)ProxyFactory.getProxy(new CalculatorService());
    int result=calculatorService.add(1, 2);
    System.out.println(result);
    }
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    运行测试类,输出结果

    com.replace.cg.CalculatorService@121714c111com.replace.cg.CalculatorService$$EnhancerByCGLIB$$481ab534
    0
    1
    2
    修改内部类中的代码,关联需求

    static Callback callback=new MethodInterceptor() {

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    //第一个参数对象是代理对象
    String name=method.getName(http://www.my516.com);
    System.out.println(target.getClass().getName()+" the "+name+" method begins");
    Object result=method.invoke(target, args);
    System.out.println(target.getClass().getName()+" the result of "+name+" method is:"+result);
    System.out.println(target.getClass().getName()+" the "+name+" method ends");
    return result; //将来调用的目标方法的返回值
    }
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    再次运行测试类,输出

    com.replace.cg.CalculatorService the add method begins
    com.replace.cg.CalculatorService the result of add method is:3
    com.replace.cg.CalculatorService the add method ends
    3
    1
    2
    3
    4
    接下来我们要证明,目标对象CalculatorService target和测试类中的代理对象new CalculatorService()到底是什么关系
    我们需要打印出产生动态对象的类,这个类也是临时的,
    //测试类的主方法中添加如下代码

    //生成使用CGlib创建动态代理对象的class文件
    System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\class");
    1
    2
    控制台输出

    CGLIB debugging enabled, writing to 'D:class'
    com.replace.cg.CalculatorService the add method begins
    com.replace.cg.CalculatorService the result of add method is:3
    com.replace.cg.CalculatorService the add method ends
    3
    1
    2
    3
    4
    5
    D盘生成如下路径文件

    复制文件到lib双击

    这个文件对应的是是动态产生代理对象的类,观察代码可知extends
    这就可以证明CGLib动态代理对象产生的动态代理对象 是我们目标类对象的子对象

    总结
    研究使用CGLib实现动态代理

    CGLib动态代理
    程序执行时通过ASM(开源的Java字节码编辑库,操作字节码)jar包动态地为被代理类生成一个代理子类,通过该代理子类创建代理对象,由于存在继承关系,所以父类不能使用final修饰。

    JDK动态代理与CGLib动态代理区别:
    1、JDK动态代理基于接口实现,所以实现JDK动态代理,必须先定义接口;CGLib动态代理基于类实现;
    2、JDK动态代理机制是委托机制,委托hanlder调用原始实现类方法;CGLib则使用继承机制,被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋值给接口。

    动态代理优点:
    1、静态代理在程序执行前需手动创建代理类,如果需要很多代理类,每一个都手动创建不仅浪费时间,而且可能产生大量重复性代码,此时我们就可以采用动态代理。
    2、动态代理通过InvocationHandler接口invoke方法或MethodIn
    ---------------------

  • 相关阅读:
    IntelliJ IDEA java项目导入jar包,打jar包
    intelliJ idea运行新的test功能时,报错:class not found "....." empty test suite
    WEBSERVICE之JDK开发webservice
    Linux uname 命令 打印系统信息
    IDEA中 @override报错的解决方法
    使用VMware搭建3台一模一样的Linux虚拟机
    java使用httpclient封装post请求和get的请求
    在Centos中yum安装和卸载软件的使用方法
    JAVA面试题:69道Spring面试题和答案
    JAVA面试题:equals()方法和== 区别
  • 原文地址:https://www.cnblogs.com/hyhy904/p/11155029.html
Copyright © 2011-2022 走看看