干货小吃休闲食品代理 干货代理的流程( 三 )

import net.sf.cglib.core.DebuggingClassWriter;import net.sf.cglib.proxy.Enhancer; public class Client {public static void main(String[] args) {// 代理类class文件存入本地磁盘方便我们反编译查看源码System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");// 通过CGLIB动态代理获取代理对象的过程Enhancer enhancer = new Enhancer();// 设置enhancer对象的父类enhancer.setSuperclass(HelloService.class);// 设置enhancer的回调对象enhancer.setCallback(new MyMethodInterceptor());// 创建代理对象HelloService proxy= (HelloService)enhancer.create();// 通过代理对象调用目标方法proxy.sayHello();}}JDK代理要求被代理的类必须实现接口,有很强的局限性 。
而CGLIB动态代理则没有此类强制性要求 。简单地说,CGLIB会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理(前置处理、后置处理等) 。
总结一下CGLIB在进行代理的时候都进行了哪些工作

  • 生成的代理类继承被代理类 。在这里我们需要注意一点:如果委托类被final修饰,那么它不可被继承,即不可被代理;同样,如果委托类中存在final修饰的方法,那么该方法也不可被代理
  • 代理类会为委托方法生成两个方法,一个是与委托方法签名相同的方法,它在方法中会通过super调用委托方法;另一个是代理类独有的方法
  • 当执行代理对象的方法时,会首先判断一下是否存在实现了MethodInterceptor接口的CGLIB$CALLBACK_0;,如果存在,则将调用MethodInterceptor中的intercept方法
在intercept方法中,我们除了会调用委托方法,还会进行一些增强操作 。在Spring AOP中,典型的应用场景就是在某些敏感方法执行前后进行操作日志记录
在CGLIB中,方法的调用并不是通过反射来完成的,而是直接对方法进行调用:通过FastClass机制对Class对象进行特别的处理,比如将会用数组保存method的引用,每次调用方法的时候都是通过一个index下标来保持对方法的引用
Fastclass机制CGLIB采用了FastClass的机制来实现对被拦截方法的调用 。
FastClass机制就是对一个类的方法建立索引,通过索引来直接调用相应的方法
public class test10 {//这里,tt可以看作目标对象,fc可以看作是代理对象;首先根据代理对象的getIndex方法获取目标方法的索引,//然后再调用代理对象的invoke方法就可以直接调用目标类的方法,避免了反射public static void main(String[] args){Test tt = new Test();Test2 fc = new Test2();int index = fc.getIndex("f()V");fc.invoke(index, tt, null);}}class Test{public void f(){System.out.println("f method");}public void g(){System.out.println("g method");}}class Test2{public Object invoke(int index, Object o, Object[] ol){Test t = (Test) o;switch(index){case 1:t.f();return null;case 2:t.g();return null;}return null;}//这个方法对Test类中的方法建立索引public int getIndex(String signature){switch(signature.hashCode()){case 3078479:return 1;case 3108270:return 2;}return -1;}}上例中,Test2是Test的Fastclass,在Test2中有两个方法getIndex和invoke 。
在getIndex方法中对Test的每个方法建立索引,并根据入参(方法名+方法的描述符)来返回相应的索引 。
Invoke根据指定的索引,以ol为入参调用对象O的方法 。这样就避免了反射调用,提高了效率
三种代理方式之间对比
代理方式
实现
优点
缺点
特点
JDK静态代理
代理类与委托类实现同一接口,并且在代理类中需要硬编码接口
实现简单,容易理解
代理类需要硬编码接口,在实际应用中可能会导致重复编码,浪费存储空间并且效率很低


特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。