当前位置:首页 > CN2资讯 > 正文内容

Java 动态代理(Proxy)java 动态代理 静态代理

2天前CN2资讯

主要是通过 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口。 Proxy 类主要用来获取动态代理对象,InvocationHandler 接口用来约束调用者行为。

AD:51CTO云计算架构师峰会 抢票进行中!

动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实,代理对象对客户隐藏了实际对象。动态代理可以对请求进行其他的 一些处理,在不允许直接访问某些类,或需要对访问做一些特殊处理等,这时候可以考虑使用代理。目前 Java 开发包中提供了对动态代理的支持,但现在只支持对接口的实现。

主要是通过 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口。 Proxy 类主要用来获取动态代理对象,InvocationHandler 接口用来约束调用者行为。

“写一个 ArrayList 类的代理,其内部实现和 ArrayList 中完全相同的功能,并可以计算每个方法运行的时间。”这是一份考题上的题目,没有答案,来看下实现:

  • package example;  
  • import java.lang.reflect.InvocationHandler;  
  • import java.lang.reflect.Method;  
  • import java.lang.reflect.Proxy;  
  • import java.util.ArrayList;  
  • import java.util.List;  
  • import java.util.concurrent.TimeUnit;  
  • /**  
  •  * -----------------------------------------  
  •  * @描述  TODO  
  •  * @作者  fancy  
  •  * @邮箱  [email protected]  
  •  * @日期  2012-8-27 <p>  
  •  * -----------------------------------------  
  •  */ 
  • public class ProxyApp {  
  •  
  •  
  •     public static void main(String[] args){  
  •           
  •         //ArrayList代理,通过代理计算每个方法调用所需时间  
  •         List<Integer> arrayListProxy = (List<Integer>)Proxy.newProxyInstance(  
  •             ArrayList.class.getClassLoader(),   /*定义代理类的类加载器,用于创建代理对象,不一定必须是ArrayList,也可以是其他的类加载器*/ 
  •             ArrayList.class.getInterfaces(),     /*代理类要实现的接口列表*/ 
  •             new InvocationHandler() {            /*指派方法调用的调用处理程序,这里用了匿名内部类*/ 
  •                   
  •                 private ArrayList<Integer> target = new ArrayList<Integer>(); //目标对象(真正操作的对象)  
  •                 /**  
  •                  * <B>方法描述:</B>  
  •                  * <p style="margin-left:20px;color:#A52A2A;">  
  •                  * 在代理实例上处理方法调用并返回结果  
  •                  * @param proxy     代理对象(注意不是目标对象)  
  •                  * @param method  被代理的方法  
  •                  * @param args         被代理的方法的参数集  
  •                  * @return <span style="color: #008080;"> 返回方法调用结果 </span>  
  •                  */ 
  •                 @Override 
  •                 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  •                       
  •                     long beginTime = System.currentTimeMillis();  //开始时间  
  •                     TimeUnit.MICROSECONDS.sleep(1);  
  •                     Object obj = method.invoke(target, args);          //实际调用的方法,并接受方法的返回值  
  •                     long endTime = System.currentTimeMillis();   //结束时间  
  •                     System.out.println("[" + method.getName() + "] spend " + (endTime - beginTime) + " ms");  
  •                     return obj;   //返回实际调用的方法的返回值  
  •                       
  •                 }  
  •                   
  •             }  
  •         );  
  •         arrayListProxy.add(2);  
  •         arrayListProxy.add(4);  
  •         System.out.println("--------- 迭代 ---------");  
  •         for(int i : arrayListProxy){  
  •             System.out.print(i + "\t");  
  •         }  
  •     }  
  • 后台打印输出结果:

     [add] spend 2 ms
    [add] spend 1 ms
    --------- 迭代 ---------
    [iterator] spend 1 ms
    2 4

    从代码上来看,用到了匿名内部类,这样一来,InvocationHandler 只能用一次,如果多个地方都需要用到这样一个相同的 InvocationHandler,可以将其抽象出来成为一个单独的类:

  • package test;  
  • import java.lang.reflect.InvocationHandler;  
  • import java.lang.reflect.Method;  
  • import java.util.concurrent.TimeUnit;  
  • public class MyInvocationHandler implements InvocationHandler{  
  •     private Object target; //目标对象      
  •     public MyInvocationHandler(Object target){  
  •         this.target = target;  
  •     }  
  •     @Override 
  •     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {          
  •         long beginTime = System.currentTimeMillis();  
  •         TimeUnit.MICROSECONDS.sleep(1);  
  •         Object obj = method.invoke(target, args);  
  •         long endTime = System.currentTimeMillis();  
  •         System.out.println("[" + method.getName() + "] spend " + (endTime - beginTime) + " ms");  
  •         return obj;      
  •     }  
  • 客户端调用改成:

  • package example;  
  • import java.lang.reflect.Proxy;  
  • import java.util.ArrayList;  
  • import java.util.List;  
  • /**  
  •  * -----------------------------------------  
  •  * @描述  TODO  
  •  * @作者  fancy  
  •  * @邮箱  [email protected]  
  •  * @日期  2012-8-27 <p>  
  •  * -----------------------------------------  
  •  */ 
  • public class ProxyApp {  
  •     public static void main(String[] args){          
  •         //ArrayList代理,通过代理计算每个方法调用所需时间  
  •         List<Integer> arrayListProxy = (List<Integer>)Proxy.newProxyInstance(  
  •             ArrayList.class.getClassLoader(),     /*定义代理类的类加载器,用于创建代理对象,不一定必须是ArrayList,也可以是其他的类加载器*/ 
  •             ArrayList.class.getInterfaces(),       /*代理类要实现的接口列表*/ 
  •             new MyInvocationHandler(new ArrayList<Integer>())         /*指派方法调用的调用处理程序,这里用了匿名内部类*/ 
  •         );  
  •         arrayListProxy.add(2);  
  •         arrayListProxy.add(4);  
  •         System.out.println("--------- 迭代 ---------");  
  •         for(int i : arrayListProxy){  
  •             System.out.print(i + "\t");  
  •         }  
  •     }  
  • 从上面代码看来,客户端知道代理的实际目标对象,还知道怎么样去创建这样一个代理对象,如果想把这些信息全部对客户端隐藏起来,可以将这些代码挪到一个类中,将它们封装起来:

  • package example;  
  • import java.lang.reflect.InvocationHandler;  
  • import java.lang.reflect.Method;  
  • import java.lang.reflect.Proxy;  
  • import java.util.ArrayList;  
  • import java.util.List;  
  • import java.util.concurrent.TimeUnit;  
  • /**  
  •  * -----------------------------------------  
  •  * @描述  TODO  
  •  * @作者  fancy  
  •  * @邮箱  [email protected]  
  •  * @日期  2012-8-27 <p>  
  •  * -----------------------------------------  
  •  */ 
  • public class ProxyUtil {  
  •     public enum ArrayListProxy {  
  •         PROXY;       
  •         private Object target;    
  •         ArrayListProxy(){  
  •             this.target = new ArrayList<Object>();  
  •         }  
  •         public List getInstance(){  
  •               
  •             return (List)Proxy.newProxyInstance(ArrayList.class.getClassLoader(), ArrayList.class.getInterfaces(),  
  •                     new InvocationHandler() {     
  •                         @Override 
  •                         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  •                               
  •                             long beginTime = System.currentTimeMillis();  
  •                             TimeUnit.MICROSECONDS.sleep(1);  
  •                             Object obj = method.invoke(target, args);  
  •                             long endTime = System.currentTimeMillis();  
  •                             System.out.println("[" + method.getName() + "] spend " + (endTime - beginTime) + " ms");  
  •                             return obj;   
  •                         }  
  •                     });  
  •         }  
  •     }  
  • 客户端调用改成:

  • package example;  
  • import java.util.List;  
  • import example.ProxyUtil.ArrayListProxy;  
  • /**  
  •  * -----------------------------------------  
  •  * @描述  TODO  
  •  * @作者  fancy  
  •  * @邮箱  [email protected]  
  •  * @日期  2012-8-27 <p>  
  •  * -----------------------------------------  
  •  */ 
  • public class ProxyApp {  
  •     public static void main(String[] args){  
  •         List<Integer> arrayListProxy = ArrayListProxy.PROXY.getInstance();  
  •         arrayListProxy.add(2);  
  •         arrayListProxy.add(4);  
  •         System.out.println("--------- 迭代 ---------");  
  •         for(int i : arrayListProxy){  
  •             System.out.print(i + "\t");  
  •         }  
  •     }  
  • 上面代码中用到了枚举 enum,如果不想用枚举,就改用普通类来实现就行了。

    原文链接:http://www.blogjava.net/fancydeepin/archive/2012/08/27/java_proxy.html

      你可能想看:

      扫描二维码推送至手机访问。

      版权声明:本文由皇冠云发布,如需转载请注明出处。

      本文链接:https://www.idchg.com/info/25106.html

      分享给朋友:

      “Java 动态代理(Proxy)java 动态代理 静态代理” 的相关文章

      AS7473在网络数据传输中的重要性与应用探究

      AS7473简介 AS7473是一个重要的ASN编号,主要与网络数据传输和路由相关。它在信息技术领域中扮演着至关重要的角色,连接着不同的网络节点,确保数据能够顺利传输。想象一下,在这个数字化时代,数据的传输速度和准确性直接影响着我们的工作效率与信息交流。因此,AS7473的定义与重要性绝不容小觑。...

      高性能HKT VPS服务评测与应用指南

      HKT VPS概述 什么是HKT VPS HKT VPS其实就是基于香港HKT网络架构的虚拟专用服务器,提供了强大的性能和灵活的可配置性。我从多个服务商的不同产品中了解到,HKT VPS非常适合对网络速度和稳定性要求较高的用户。无论是游戏玩家还是企业用户,都能通过它享受到快速的上传和下载速度。 HK...

      探索4837线路:高速度、稳定性与价格优势的网络选择

      在当今网络时代,选择合适的线路对于提高上网体验至关重要。4837线路就是其中一个备受关注的选项。它主要指在回国或出国前,通过一个名为4837的节点进行连接,进行跨国网络传输。这个线路归类为联通线路,其特点在于相对负载较低,使得整体表现更胜一筹。经过近年来的广泛应用,4837线路逐渐成为热门选择。 我...

      VPS IP被封怎么办?常见原因与解决方案分析

      在使用VPS的过程中,有时候会遇到VPS IP被封的情况,这对很多用户来说,会带来一些困扰。虽然情况不同,但通常来说,下列几个原因是比较常见的,了解这些原因能够帮助我们更好地避免封禁。 首先,敏感操作常常是导致IP被封的重要原因之一。比如,如果你进行了一些网络爬虫、频繁请求某个网站内容,或者试图访问...

      AMD Ryzen VPS 性能测评:RackNerd 的优越体验与机房对比

      当我开始使用RackNerd的VPS服务时,我被它的低价和强大性能所吸引。作为一个刚入驻云计算的用户,我知道许多商家提供VPS,但RackNerd以十美元每年的超低价格引起了我的注意。而真正让我印象深刻的是它的稳定性与出色的售后服务。我曾多次遇到技术问题,售后支持总能在第一时间给我回应,这让我感受到...

      zgocloud:提升数据管理效率的创新云计算解决方案

      zgocloud的定义与背景 在当今数字化快速发展的时代,zgocloud作为一种创新的云计算解决方案逐渐崭露头角。简单来说,zgocloud是一种基于云技术的平台,可以提供灵活的存储和计算能力。它的设计旨在更好地满足不同企业和个人用户在数据处理和管理方面的需求。成立之初,zgocloud就定位于提...