代理 静态代理 
主要目的是扩展原有类的功能
 
例子: 1 2 3 4 public  interface  Handler      void  handle (String data)  } 
1 2 3 4 5 6 7 public  class  HandlerImpl  implements  Handler      @Override      public  void  handle (String data)           System.out.println("handle: "  + data);     } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public  class  HandlerProxy  implements  Handler     private  Handler mHandler;          public  HandlerProxy (Handler handler)           mHandler = handler;     }          @Override      public  void  handle (String data)           System.out.println("start handle" );         mHandler.handle(data);         System.out.println("end handle" );     } } new  HandlerProxy(new  HandlerImpl()).handle("待处理数据" );
就这样,知道缺点是被代理的类扩展了代理类也需一并扩展。
动态代理 例子: 1 2 3 4 public  interface  Handler      void  handle (String data)  } 
1 2 3 4 5 6 7 public  class  HandlerImpl  implements  Handler      @Override      public  void  handle (String data)           System.out.println("handle: "  + data);     } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public  class  MyHandler  implements  InvocationHandler           private  Handler mHandler;     public  MyHandler (Handler handler)           mHandler = handler;     }     @Override      public  Object invoke (Object proxy, Method method, Object[] args)  throws  Throwable          System.out.println("start handle" );                  Object invoke = method.invoke(mHandler, args);         System.out.println("end handle" );         return  invoke;     } } 
1 2 3 4 5 6 7 8 9 Handler o = (Handler) Proxy.newProxyInstance( 	             HandlerImpl.class.getClassLoader(),     	     	new  Class[]{Handler.class},     	         new  MyHandler(new  HandlerImpl())); o.handle("待处理数据" ); 
可以看到,动态代理跟静态代理一样,在代理类内部保存了一个委托类的实例,实际上都是调用原来的委托实例来进行需要的操作。
区别: 
动态代理跟静态代理最大的不同便是生成代理类的时期不同,静态代理是在编译期,而动态代理则是在运行时根据委托类信息动态生成 
动态代理实现的是InvocationHandler接口,而静态代理则是直接实现公共接口 
动态代理可以获得更多的运行时信息,使用起来也会更加灵活 
 
缺点: 由于最终调用实际逻辑采用方法反射调用的方式,效率并不是很高
原理: 最终通过ProxyGenerator.generateProxyClass()函数动态生成代理字节码二进制数据,然后通过native方法defineClass0将字节码加载进方法区,并获取参数为InvocationHandler的构造器,然后通过该构造器生成实例并传入我们自定义的处理器
注:android中直接通过generateProxy生成了代理类,并没有走ProxyGenerator 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 participant Proxy participant Proxy#ProxyClassFactory participant WeakCache participant WeakCache#Factory Note left of WeakCache:Proxy类里有静态实例WeakCache成员变量\n生成该实例时传入ProxyClassFactory实例 Proxy -> WeakCache:Proxy.getProxyClass0() Note right of WeakCache:优先查找缓存 WeakCache -> WeakCache:proxyClassCache.get() WeakCache -> Proxy:有缓存 Note right of WeakCache:构建Factory工厂类 WeakCache -> WeakCache:new Factory() WeakCache -> WeakCache#Factory:supplier.get() WeakCache#Factory -> Proxy#ProxyClassFactory:valueFactory.apply() Note right of Proxy#ProxyClassFactory:1.类加载器是否解析出相同的class对象 Note right of Proxy#ProxyClassFactory:2.class是否是一个接口 Note right of Proxy#ProxyClassFactory:3.数组类是否重复等判断 Note right of Proxy#ProxyClassFactory:调用defineClass0(native方法)动态生成字节码 Proxy#ProxyClassFactory -> Proxy:ProxyGenerator.generateProxyClass() \n defineClass0() Note right of Proxy:取参数为InvocationHandler构造器 Note right of Proxy:通过构造器生成实例时传入处理器 
Cglib动态代理 
CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充
通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择
git地址:https://github.com/cglib/cglib 
cglib-nodep-xxx.jar:使用nodep包不需要关联asm的jar包,jar包内部包含asm的类.
 
例子: 1 2 3 4 5 6 public  class  Handler      public  void  method_1 (String data)       public  void  method_2 (String data)       public  void  method_3 (String data)   } 
代理: 1 2 3 4 5 6 7 8 9 10 11 Handler handler = (Handler) Enhancer.create(Handler.class, new  MethodInterceptor() {     @Override      public  Object intercept (Object o, Method method, Object[] objects, MethodProxy methodProxy)  throws  Throwable          System.out.println("start handle" );                  Object result = methodProxy.invokeSuper(o, objects);         System.out.println("end handle" );         return  result;     } }); handler.method_1("待处理数据" ); 
过滤器: 
作用:可以针对不同的方法调用不同的逻辑,
注意:虽然可以在MethodInterceptor的intercept方法进行区分,但使用过滤器可以有效的减少哈希查找,提高效率
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 NoOp instance = NoOp.INSTANCE; FixedValue fixedValue = new  FixedValue() {     @Override      public  Object loadObject ()  throws  Exception          System.out.println("锁定调用结果" );         Object result = 1 ;         return  result;     } }; MethodInterceptor methodInterceptor = new  MethodInterceptor() {     @Override      public  Object intercept (Object o, Method method, Object[] objects, MethodProxy methodProxy)  throws  Throwable          System.out.println("start handle" );         Object result = methodProxy.invokeSuper(o, objects);         System.out.println("end handle" );         return  result;     } }; Handler handler = (Handler) Enhancer.create(Handler.class, null , new  CallbackFilter() {     @Override      public  int  accept (Method method)           if  (method.getName().equals("method_1" )){             return  2 ;         } else  if  (method.getName().equals("method_2" )) {             return  1 ;         }         return  0 ;     } }, new  Callback[]{instance, fixedValue, methodInterceptor}); handler.method_1("method_1" ); handler.method_2("method_2" ); handler.method_3("method_3" ); 
延迟加载: 1 2 3 4 5 6 public  class  LazyBeam      private  String name;     public  String getName ()  return  name;}     public  void  setName (String name)  this .name = name;} } 
1 2 3 4 5 6 7 8 9 10 11 LazyBeam lazyBeam = (LazyBeam) Enhancer.create(LazyBeam.class, null , new  LazyLoader() {     @Override      public  Object loadObject ()  throws  Exception          System.out.println("加载数据" );         LazyBeam lazyBeam = new  LazyBeam();         lazyBeam.setName("lazyBeam" );         return  lazyBeam;     } }); System.out.println(lazyBeam.getName()); 
1 2 3 4 5 6 7 8 9 10 11 LazyBeam lazyBeam = (LazyBeam) Enhancer.create(LazyBeam.class, null , new  Dispatcher() {     @Override      public  Object loadObject ()  throws  Exception          System.out.println("加载数据" );         LazyBeam lazyBeam = new  LazyBeam();         lazyBeam.setName("lazyBeam" );         return  lazyBeam;     } }); System.out.println(lazyBeam.getName()); 
接口生成: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 InterfaceMaker maker = new  InterfaceMaker(); maker.add(Handler.class); Class<?> aClass = maker.create(); for  (Method method : aClass.getMethods()) {    System.out.println(method.getName()); } Object obj = Enhancer.create(Object.class, new  Class[]{aClass}, new  MethodInterceptor() {     @Override      public  Object intercept (Object o, Method method, Object[] objects, MethodProxy methodProxy)  throws  Throwable          if  (method.getName().equals("method_1" )) {             System.out.println("执行方法1" );             return  "方法1" ;         }         if  (method.getName().equals("method_2" )) {             System.out.println("执行方法2" );             return  "方法2" ;         }         return  null ;     } }); Method method_1 = aClass.getMethod("method_1" , String.class); method_1.invoke(obj,"方法1" ); Method method_2 = aClass.getMethod("method_2" , String.class); method_2.invoke(obj,"方法2" ); 
原理: 表层原理: 动态生成代理类的子类,子类重写要代理的类的所有不是final/private的方法。在子类采用方法拦截的技术拦截所有父类方法的调用。
底层原理: 使用字节码处理框架ASM,来转换字节码并生成新的类。注:不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。 
优点: 相较与JDK动态代理
可以实现接口和类的代理,局限性更小【注:代理接口调用invokeSuper相当于直接调用未实现的接口方法,会直接报错 】 
由于与实际编写继承代码无异,采用的是动态用生成子类方式,方法执行效率要高 
有丰富的操作策略以适应不同的业务 
 
缺点: 由于采用继承的关系,对私有方法和final方法无法代理
包说明: net.sf.cglib.core:底层字节码处理类,他们大部分与ASM有关系。net.sf.cglib.transform:编译期或运行期类和类文件的转换net.sf.cglib.proxy:实现创建代理和方法拦截器的类net.sf.cglib.reflect:实现快速反射和C#风格代理的类net.sf.cglib.util:集合排序等工具类net.sf.cglib.beans:JavaBean相关的工具类