我的的理解,运行期间由JVM根据反射等机制动态的生成代理类java
java.lang.reflect.Proxy 框架
全部动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
java.lang.reflect.InvocationHandler 函数
这是调用处理器接口,它自定义了一个 invoke 方法,一般在该方法中实现对委托类的访问
java.lang.ClassLoader spa
这是类装载器类,负责将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,而后该类才能被使用
代码实现:点击下载代理
一个典型的动态代理建立对象过程可分为如下四个步骤: code
1. 经过实现InvocationHandler接口建立本身的调用处理器
IvocationHandler handler = new InvocationHandlerImpl(…);
2. 经过为Proxy类指定ClassLoader对象和一组interface建立动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});
3. 经过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4. 经过构造函数建立代理类实例,此时需将调用处理器对象做为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
为了简化对象建立过程,Proxy类中的newInstance方法封装了2~4,只需两步便可完成代理对象的建立。 对象
1.代理对象是怎么生成的blog
由Proxy完成, 在内部方法中调用ProxyGenerator类的静态方法generateProxyClass,这里是真正生成代理类class字节码的地方。
2.InvocationHandler的invoke方法是由谁来调用的继承
生成的代理类ProxySubject继承Proxy类实现Subject接口,实现了Subject的方法,在实现方法中,调用处理器的invoke方法
3.真实实例的方法如何被调用的索引
InvocationHander的实现类只是经过代理类的构造函数注入后, 实现了对代理类中方法调用的拦截
而invoke方法利用反射调用的是真实对象的的方法(Object result=method.invoke(proxied,args))
jdk动态代理只能代理接口,是由于生成的代理类自己 extends Proxy implement xxxInterface
CGLib采用了asm框架的字节码技术,其原理是:
经过字节码技术为一个类建立子类,并在子类中采用方法拦截的技术拦截全部父类方法的调用,顺势织入横切逻辑
net.sf.cglib.proxy.Enhancer – 主要的加强类
net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,须要用户实现
net.sf.cglib.proxy.MethodProxy -能够方便的实现对源对象方法的调用
代码实现: 点击下载
1.代理对象的生成过程由Enhancer类实现
一、生成代理类Class的二进制字节码;
二、经过Class.forName加载二进制字节码,生成Class对象;
三、经过反射机制获取实例构造,并初始化代理类对象。
2.如何调用真实实例的方法
经过FastClassInfo维护了委托类和代理类的FastClass,提出下标概念index,经过索引保存方法的引用信息,将原先的反射调用,转化为方法的直接调用
因此当调用方法时,其实是调用代理类的方法,直接调用了委托类的add方法。methodProxy.invokeSuperCGLIB$add$0CGLIB$add$0
cglib动态代理类,继承了委托类, 采用保存索引的方式调用委托类的方法
一、jdk动态代理生成的代理类和委托类实现了相同的接口;
二、cglib动态代理中生成的字节码更加复杂,生成的代理类是委托类的子类,且不能处理被final关键字修饰的方法;
三、jdk采用反射机制调用委托类的方法,cglib采用相似索引的方式直接调用委托类方法;