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

    动态代理,一般都是通过生成字节码来完成,只是生成的时机不同,而字节码的动态生成技术,不只是应用于动态代理,比如jar包,热替换等技术都是动态字节码的应用。

    生成字节码的库比如ASM,这个库基本就是按照字节码规范定义的格式来操作,比较底层,像cglib这种工具是基于asm开发的。再往上的一些工具比如Javassist已经抽象

    到和直接编写java文件没太大区别了。

    1. 运行时代理

    在运行时创代理类的字节码,这种技术有jdk原生的proxy,还有用cglib实现代理

    1.1 Jdk代理

    这两种代理都是在运行时生成代理类,首先jdk动态代理的用法,比如对XX接口代理,

    XX x = (XX)Proxy.newProxyInstance(classLoader, XX, handler);

    这句就是创建一个XX的代理类,handler里面一般会组合进XX的一个实现,这样在调用handler的invoke方法的时候就可以调用具体实现的方法。

    newProxyInstance动态生成的类其实是一个实现XX接口的类,而且这个类接收handler作为构造方法,这样调用生成的XX实现类的方法时候就可以调用handler的方法,

    和写一个简单代理的代码是完全相同的,唯一不同的就是Proxy类是由jdk在运行时动态生成的。

    1.2 cglib代理

    从原理上讲,cglib代理和jdk代理没有区别,同样是在运行时生成字节码,通过classloader创建实例,不过cglib解决了被代理的target必须是接口的问题

    比如现在有个OO类需要被代理,

    Enhancer enhancer = new Enhancer(); 

    enhancer.setSuperclass(OO);

    enhancer.setCallback(handler);

    OO o = (OO) enhancer.create();

    动态生成不是接口的实现类,而是一个继承了OO这个类的代理类,这个代理类重写了OO的public方法,当调用OO的方法的时候,通过调用组合进去的handler的相应方法

    来实现,因为是通过继承,重写的方式,所以像static method, protected method, finnal class都没法代理。

    1.3 通过jvmti或者jvmagent来实现

    jvmagent也是基于jvmti来实现的,jvmti是jvm运行时的一些hook,aspectJ的其中一种织入方式是基于这个实现的,启动的时候必须加载一个javaagent

    2. 编译时

    java类都需要编译成.class字节码文件,这种动态代理的方式,就是在编译的时候修改了字节码,但是需要特殊的编译器,代表的是aspectJ

    2.1 AspectJ

    首先,有自己的语法,之前都是用javac编译,现在需要特殊的编译工具,这个maven有aspectj的插件。编译出来的东西也没必要弄个代理类了,直接把代理做的一些事情编码到之前代码的上下文里就可以了。这种方法基本什么都能代理。

    然后还需要说明一下,编译时又可以分为两种,一种是和java源文件一起织入,还有一种是织入已经存在的.class字节码文件,本质上没有太大区别

  • 相关阅读:
    SQL表连接查询inner join left join right join full join ...
    希尔伯特空间回顾(简直太好了)
    pytorch的matmul怎么广播
    pytorch怎么抽取中间的特征或者梯度
    winedt102安装
    数据挖掘 关联规则
    git 命令
    caffe: c++11支持
    匈牙利算法
    ubuntu两个conda安装和切换
  • 原文地址:https://www.cnblogs.com/23lalala/p/5550472.html
Copyright © 2011-2022 走看看