java 动态代理总结

Posted 23lalala

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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字节码文件,本质上没有太大区别

 

以上是关于java 动态代理总结的主要内容,如果未能解决你的问题,请参考以下文章

Java静态代理和动态代理总结

java 动态代理总结

java开发必学知识:动态代理

Java 动态代理 Proxy

java中的动态代理

JAVA 动态代理原理和实现