本文最后更新于:May 2, 2022 am
                
              
            
            
              积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里,不积小流无以成江海。齐骥一跃,不能十步,驽马十驾,功不在舍。面对悬崖峭壁,一百年也看不出一条裂缝来,但用斧凿,能进一寸进一寸,能进一尺进一尺,不断积累,飞跃必来,突破随之。
目录 静态代理 静态代理就和平常自己写一些工具类差不多。
静态代理实现步骤:
定义一个接口及其实现类; 
创建一个代理类同样实现这个接口 
将目标对象注入进代理类,然后在代理类的对应方法调用目标类中的对应方法。这样的话,我们就可以通过代理类屏蔽对目标对象的访问,并且可以在目标方法执行前后做一些自己想做的事情。(简单说就是把被代理对象进行一次封装) 
 
实现 以一个邮件发送为例。
接口 package  com.proxyStu.staticProxy;public  interface  EmailSendService  void  sendMSG (String email,String msg) 
实现类 package  com.proxyStu.staticProxy;public  class  EmailSendServiceImpl  implements  EmailSendService @Override public  void  sendMSG (String email,String msg)  "发送给 " +email+" 的消息为:" +msg);
代理类 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 package  com.proxyStu.staticProxy;public  class  EmailSendProxy  implements  EmailSendService private  EmailSendService emailSendService;this .emailSendService = ess;@Override public  void  sendMSG (String email, String msg)  "发送前的处理逻辑" );"发送后的处理逻辑" );
使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package  com.proxyStu.staticProxy;public  class  ProxyTest  public  static  void  main (String[] args)  new  EmailSendServiceImpl();new  EmailSendProxy(emss);"123465@qq.com" , "Hello World!" );123465 @qq .com 的消息为:Hello World!
动态代理 动态代理的实现方式有很多种,比如 JDK 动态代理 、CGLIB 动态代理 等等。
JDK动态代理 只能代理实现了接口的类或者直接代理接口。 
介绍 Java 动态代理机制中 InvocationHandler 接口和 Proxy 类是核心。  
我们会使用 newProxyInstance() 来生成一个代理对象。源码中为:
public  static  Object newProxyInstance (ClassLoader loader,                                           Class<?>[] interfaces,                                           InvocationHandler h) 
而这个方法一共有 3 个参数:
loader  :类加载器,用于加载代理对象。即加载我们自己写的类。
interfaces  : 被代理类实现的一些接口;即类中的方法。
h  : 实现了 InvocationHandler 接口的对象;自定义重写的一个类,该类实现了InvocationHandler接口,用于自定义一些处理逻辑。
 
要实现动态代理,还需要实现InvocationHandler 来自定义处理逻辑。 当我们的动态代理对象调用一个方法时,这个方法的调用就会被转发到实现InvocationHandler 接口类的 invoke 方法来调用。源码
public  interface  InvocationHandler  public  Object invoke (Object proxy, Method method, Object[] args)         throws  Throwable ;
三个参数:
通过Proxy 类的 newProxyInstance() 创建的代理对象在调用方法的时候,实际会调用到实现InvocationHandler 接口的类的 invoke()方法。  所以可以在 invoke() 方法中自定义处理逻辑,比如在方法执行前后做什么事情。
步骤 
定义一个接口及其实现类; 
自定义 InvocationHandler 并重写invoke方法,在 invoke 方法中我们会调用原生方法(被代理类的方法)并自定义一些处理逻辑; 
通过 Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 方法创建代理对象;这里我们可以封装成一个工厂类。 
 
实现 还是以发送一个邮件为例。
接口 package  com.proxyStu.jdkProxy;public  interface  EmailSendService  void  sendMSG (String email,String msg) 
实现类 package  com.proxyStu.jdkProxy;public  class  EmailSendServiceImpl  implements  EmailSendService  @Override public  void  sendMSG (String email,String msg)  "发送给 " +email+" 的消息为:" +msg);
代理类 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 package  com.proxyStu.jdkProxy;import  java.lang.reflect.InvocationHandler;import  java.lang.reflect.Method;public  class  myInvocationHandler  implements  InvocationHandler  private  Object target;this .target = obj;@Override public  Object invoke (Object proxy, Method method, Object[] args)  throws  Throwable "执行前的其他逻辑" );"执行后的其他逻辑" );return  res;
其实,这里就已经完成了代理。可以直接使用了。如下:
 
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 package  com.proxyStu;import  com.proxyStu.staticProxy.EmailSendService;import  com.proxyStu.staticProxy.EmailSendServiceImpl;import  java.lang.reflect.Proxy;public  class  proxyTest  public  static  void  main (String[] args)  new  EmailSendServiceImpl();new  myInvocationHandler(obj)"123456@qq.com" ,"Hello World2!" );123456 @qq .com 的消息为:Hello World2!
可以看见,在创建代理对象的时候是比较复杂的;如果需要创建多次时,那么就会出现代码的冗余,也不方便。所以,我们可以将其进行封装。
封装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package  com.proxyStu.jdkProxy;import  java.lang.reflect.Proxy;public  class  myProxyFactory  public  static  Object getProxy (Object obj) return  Proxy.newProxyInstance(new  myInvocationHandler(obj)
使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package  com.proxyStu;import  com.proxyStu.staticProxy.EmailSendService;import  com.proxyStu.staticProxy.EmailSendServiceImpl;public  class  proxyTest  public  static  void  main (String[] args)  new  EmailSendServiceImpl());"123465@qq.com" ,"Hello World3 !" );123465 @qq .com 的消息为:Hello World3 !
这样进行封装,极大的方便了使用和减少了代码量。
CGLIB 动态代理  CGLIB 可以代理未实现任何接口的类。  在 CGLIB 动态代理机制中 MethodInterceptor 接口和 Enhancer 类是核心。 
总结