动态代理笔记

以前我眼里动态代理一直是个很神秘的东西,面试一旦问到必然摇头回答不知道

想办法理一下,目前动态代理有使用JDK类库 和使用CGLIB 两种方式

JDK类库的大概用法是这样的:

写一个类 写一个接口 叫MyClassMyClassImpl

写一个Handler类,实现InvocationHandler这个JDK反射包里的接口,构造器传入一个MyClass的实例,并且覆盖invoke方法,然后在invoke方法中实现具体的逻辑

如果要使用动态代理,就需要使用JDK的Proxy.newProxyInstance()方法,传入类加载器、代理需要实现的接口、你写的Handler类的一个新实例,并且传入一个MyClassImpl作为这个新实例的构造函数参数。

就可以在方法调用时 动态生成Proxy类,并且实际执行Handler中的逻辑了。

这一套看起来很眼熟,Spring的AOP相关类库 就是对使用动态代理的简化。


但是JDK动态代理 要求被代理的类必须实现接口,碰到没有接口的类 就必须使用CGLIB来操作字节码了。

其实和JDK库类似,只不过实际使用的类库不太一样:

首先写一个MyClass类,再写一个Interceptor类 实现MethodInterceptor这个CGLIB的接口,覆盖intercept方法,然后在intercept方法里实现具体的逻辑

而实际使用动态代理时,new 一个 Enhancer对象(CGLIB提供这个类),设置要代理的类和Interceptor对象,再使用create()方法创建被代理后的对象。

这样做,所有非final方法都会被代理。而由于生成的代理类是继承了原类的,所以final类被代理时会抛出异常。

对于Object类,JDK只代理hashCode()equals()toString(),按官方文档的说法,是“和接口方法一样处理”;

而CGLIB则是代理wait(),notify()notifyAll(),getClass()四个方法,因为它们是final的。

作者

Mother Ship

发布于

2018-12-12

更新于

2023-02-13

许可协议

评论