在工作中用代理的地方非常多,但一直还没仔细来看代理的原理,今天被同事提到,所以自己开始仔细研究了一下这两者代理都做了些什么工作,并通过编写测试用例的方式来对两种代理原理作理解。
在自行看代码之前,初步问了一下朋友,大概解释这两者区别是,java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。这是朋友说的,我并没自己实验过,所以也没映象,所以开始自己动手实践之:
java动态代理
使用方法:
接口:
public interface Call {
void doCall(String doCall);
}
public interface Processor {
void doProcess(String doProcess);
}
实现类:
public class ServiceImpl implements Call, Processor {
public void doCall(String doCall) {
System.out.println("doCall");
}
public void doProcess(String doProcess) {
System.out.println("doProcess");
}
}
具体代理Handler:
public class ServiceHandler implements InvocationHandler {
private Call callService;
public ServiceHandler(Call callService) {
this.callService = callService;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxyMethod=" + method.getName());
Object obj = method.invoke(this.callService, args);
System.out.println("after invoke!");
return obj;
}
}
使用java动态代理:
public class JdkProxyTest {
@Test
public void testJdkProxy() {
Call call = new ServiceImpl();
ServiceHandler handler = new ServiceHandler(call);
Call callProxy = (Call) Proxy.newProxyInstance(call.getClass().getClassLoader(),
new Class[]{Call.class}, handler);
callProxy.doCall("test");
}
}
最终效果就是执行代理接口的doCall方法之前,该方法被ServiceHandler给处理了。
通过查看java.lang.reflect.Proxy代码,大致拟了一下它的实现原理:
1. 取到
new Class[]{Call.class}
这里所有接口,通过
Class.forName
把接口类加载到JVM,放到内部Set里保存,把接口的完整名字保存,带包名的接口名字,并以把这组接口名称数组转换成List作为key,用于下面生成代理类后保存到内部Map的key.也就是相当于这一组的接口名称对应的一个生成的代理类
2. 主要是从内存里找是否之前已经生成好了这同一组接口的代理类,如果有就直接拿出。这里第一次是需要新建立的,所以开始创建代理,首先检查代理目标接口的访问控制符是否是默认包级别的,如果是就需要给生成的代理类设置目标接口同样的包名,才能默认访问这种级别下的接口。如果这种有默认访问控制标识符的目标接口,又有不同包名的目标接口,则会报出错误。否则其它情况,是给的无包名的代理类,生成的代理类的默认名称是$Proxy开头加Proxy里标识唯一类名的数字,是静态long型变量,每次生成一次代理类会累加
3. 调用
ProxyGenerator.generateProxyClass(proxyName, interfaces)
动态生成class字节码类,该类相当于是Proxy的子类,实现了需要代理的接口方法,并在每个方法里调用了InvocationHandler的invoke方法,而我们自己实现的InvocationHandler接口类里完成了以反射方式最终对目标业务类的接口方法进行调用。所以此种方式实现的动态代理只能代理接口方法,对具体类的代理不能实现。
最终动态生成Proxy子类方法在下面这一句代码
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);
这里应该是根据指定接口和代理类名生成class字节数据,再用这代码生成最终类
proxyClass = defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
java动态代理不能代理目标类的超类,原因是java动态代理的设计就是目标代理类是继承了Proxy,而java是不支持多继承,也就无法继承目标类的超类。
分享到:
相关推荐
java动态代理和cglib动态代理示例分享共5页.pdf.zip
java代理机制 JDK动态代理和cglib代理 详解
jdk 和 cglib的简单动态代理,闲来无事 写写。有需要的朋友可以看看
JAVA动态代理实现Demo(JDK动态代理和CGLIB动态代理)
实现java动态代理的两个实例,jdk动态代理和cglib
NULL 博文链接:https://pluto418.iteye.com/blog/1692218
java静态代理 jdk动态代理 cglib动态代理 代理原理
Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理)
Java JDK代理、CGLIB、AspectJ代理分析比较
JAVA JDK静态代理、动态代理、CGlib代理的代码演示 为对象增加功能
CGLIB是一个强大的、高性能的代码生成库。它被广泛使用在基于代理的AOP框架(例如Spring AOP和...EasyMock和jMock作为流行的Java测试库,它们提供Mock对象的方式来支持测试,都使用了CGLIB来对没有接口的类进行代理。
java动态代理(JDK和cglib).pdfjava动态代理(JDK和cglib).pdfjava动态代理(JDK和cglib).pdfjava动态代理(JDK和cglib).pdfjava动态代理(JDK和cglib).pdf
java动态代理(JDK和cglib)共10页.pdf.zip
Java的动态代理,包括JDK自带的和cglib所集成的。
在java编程使用CGLIB做动态代理时需要CGLIB依赖包支持,没有这个支持包,当导入import net.sf.cglib.proxy.Enhancer;或者import net.sf.cglib.proxy.MethodProxy;类似包时会提示错误,所以分享出来同大家共勉。
附件为java 动态代理实例,有全码,包括测试代码。 代码少,注释全。 对理解代理非常不错。
java动态代理(JDK和cglib)共10页.pdf.zip
cglib和asm搭配的jar,方便你使用动态代理
java常用设计模式及JDK与CGLIB实现动态代理区别(源码) /** * 使用cglib动态代理 * @author * */ public class BookFacadeProxy implements MethodInterceptor{ private Object target; @Override public...