黑马程序员——Java中的动态代理

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ---------------------

代理也是基本的设计模式之一,而代理通常也作为一种中介对象。

Java的动态代理的思想更向前迈进了一步,因为它可以动态地创建代理并动态地处理对所代理的方法的调用。在动态代理上所做的所有的调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的对策。


下面就以一个创建动态代理类和查看的方法的代码来看看吧:

首先我们来定义下两个接口:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package cn.itcast.day3;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. public interface Advice {  
  6.      void beforeMethod(Method method);//定义之前的接口  
  7.      void afterMethod(Method method);//定义之后的接口  
  8. }  

接下来呢  就是实现我们定义的接口:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package cn.itcast.day3;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. public class MyAdvice implements Advice {  
  6. long beginTime=0;  
  7.     @Override  
  8.     public void beforeMethod(Method method) {  
  9.         // TODO Auto-generated method stub  
  10.         System.out.println("开始学习啦!");  
  11.         beginTime=System.currentTimeMillis();//定义开始时间(毫秒)  
  12.     }  
  13.   
  14.     @Override  
  15.     public void afterMethod(Method method) {  
  16.         // TODO Auto-generated method stub        
  17.         System.out.println("开始上班啦!");  
  18.         long endTime=System.currentTimeMillis();//定义结束时间(毫秒)  
  19.         System.out.println(method.getName()+"运行时间为"+(endTime-beginTime)+"毫秒");  
  20.     }  
  21.   
  22. }  
下一步我们来调用实现接口的方法 :


[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package cn.itcast.day3;  
  2.   
  3. import java.lang.reflect.Constructor;  
  4. import java.lang.reflect.InvocationHandler;  
  5. import java.lang.reflect.Method;  
  6. import java.lang.reflect.Proxy;  
  7. import java.util.ArrayList;  
  8. import java.util.Collection;  
  9.   
  10. /*创建动态代理类及查看其方法*/  
  11. public class ProxyTest {  
  12.     public static void main(String[] args) throws Exception {  
  13.         Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);  
  14.         System.out.println(clazzProxy1.getName());  
  15.         System.out.println("-------begin constructors lists--------");  
  16.         Constructor[] constructors=clazzProxy1.getConstructors();  
  17.         for(Constructor constructor : constructors){  
  18.             String name=constructor.getName();  
  19.             StringBuilder sBuilder=new StringBuilder(name);  
  20.             sBuilder.append('(');  
  21.             Class[] clazzParams=constructor.getParameterTypes();  
  22.             //把构造函数里面的值取出来  
  23.             for(Class clazzParam : clazzParams){  
  24.                 sBuilder.append(clazzParam.getName()).append(',');  
  25.             }  
  26.             if(clazzParams!=null&&clazzParams.length!=0)  
  27.                 sBuilder.deleteCharAt(sBuilder.length()-1);  
  28.             sBuilder.append(')');  
  29.             System.out.println(sBuilder.toString());  
  30.         }  
  31.         System.out.println("-------begin Method lists--------");  
  32.         Method[] methods=clazzProxy1.getMethods();  
  33.         for(Method method : methods){  
  34.             String name=method.getName();  
  35.             StringBuilder sBuilder=new StringBuilder(name);  
  36.             sBuilder.append('(');  
  37.             Class[] clazzParams=method.getParameterTypes();  
  38.             //把构造函数里面的值取出来  
  39.             for(Class clazzParam : clazzParams){  
  40.                 sBuilder.append(clazzParam.getName()).append(',');  
  41.             }  
  42.             if(clazzParams!=null&&clazzParams.length!=0)  
  43.                 sBuilder.deleteCharAt(sBuilder.length()-1);  
  44.             sBuilder.append(')');  
  45.             System.out.println(sBuilder.toString());  
  46.         }  
  47.         //创建实例对象,接收InvocationHandler对象  
  48.         System.out.println("-------begin instance Object--------");  
  49.         //Object obj=clazzProxy1.newInstance();如果这样写,运行时就会出错。所以要先得到构造函数  
  50.          Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);  
  51.         //新建一个自己的实现类,实现InvocationHandler接口  
  52.         class MyInvocationHandler implements InvocationHandler{  
  53.   
  54.             @Override  
  55.             public Object invoke(Object proxy, Method method, Object[] args)  
  56.                     throws Throwable {  
  57.                 // TODO Auto-generated method stub  
  58.                 return null;  
  59.             }  
  60.         }  
  61.             Collection proxy1=(Collection)constructor.newInstance(new MyInvocationHandler());  
  62.             System.out.println(proxy1);  
  63.             proxy1.clear();//调用无返回值的方法就会成功  
  64.             //proxy1.size();//这里会报空指针异常,size()方法有返回值  
  65.             Collection proxy2=(Collection)constructor.newInstance(new InvocationHandler(){  
  66.                 @Override  
  67.                 public Object invoke(Object proxy, Method method, Object[] args)  
  68.                         throws Throwable {  
  69.                     return null;  
  70.                 }                 
  71.             });  
  72.             final ArrayList target=new ArrayList();  
  73.             Collection proxy3 =(Collection)getProxy(target,new MyAdvice());  
  74.             proxy3.add("a");  
  75.             proxy3.add("b");  
  76.             proxy3.add("c");  
  77.             System.out.println(proxy3.size());  
  78.           
  79.     }  
  80.   
  81.     private static Object getProxy(final Object target,final Advice advice) {  
  82.         Object proxy3=Proxy.newProxyInstance(  
  83.                 target.getClass().getClassLoader(),  
  84.                 //new Class[]{Collection.class},  
  85.                 target.getClass().getInterfaces(),  
  86.                 new InvocationHandler() {                         
  87.                     public Object invoke(Object proxy, Method method, Object[] args)  
  88.                             throws Throwable {  
  89.                         //ArrayList target=new ArrayList();如果这句话在invoke方法内,就会输出0,无法获取数量  
  90.                         /*long beginTime=System.currentTimeMillis();//定义开始时间(毫秒) 
  91.                         Object reVal=method.invoke(target, args); 
  92.                         long endTime=System.currentTimeMillis();//定义结束时间(毫秒) 
  93.                         System.out.println(method.getName()+"运行时间为"+(endTime-beginTime)+"毫秒"); 
  94.                         return reVal;*/  
  95.                           
  96.                         advice.beforeMethod(method);  
  97.                         Object reVal=method.invoke(target, args);  
  98.                         advice.afterMethod(method);                           
  99.                         return reVal;  
  100.                     }  
  101.   
  102.                       
  103.                 }  
  104.                 );  
  105.         return proxy3;  
  106.     }  
  107. }  

上面的代码中若创建一个动态代理的类,就要实现InvocationHandler接口。

因为动态代理类可以将所有调用重定向到处理器,所以通常会向调用处理器的构造器传递给一个“实际”对象的引用,使得调用处理器在执行中介任务时,可以将请求转发。

invoke()方法中传递进来代理对象,用于以防止你需要区分请求的来源。当然也可以传递其他的参数来过滤某些方法的调用。



----------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值