动态代理(2)

我们看 具体代码:
public  void  pro()  throws  Exception{
     Tank  t  =  new  Tank ();
     InvocationHandler  h  =  new  TimeHandler(  t );
     Moveable  m  = (Moveable)Proxy.newProxyInstance(Moveable.  class ,  h );           
     }
这个就是生产代理的代码,上篇看过了。

Moverable 接口:
public  interface  Moveable {
      public  void  move();
}
Moverable 接口有一个move方法。

Tank 类:
public  class  Tank  implements  Moveable{
      @Override
      public  void  move() {
           System.  out .println(  "Tank moving ..." );
             try  {
                Thread. sleep( new  Random().nextInt(10000));
           }  catch  (InterruptedException  e ) {
                  e .printStackTrace();
           }
     }    
}

这里很简单 就是有一个类叫tank 有个方法叫move可以随机sleep 时间。就是随机暂停一会。

我们现在希望把他通过动态代理,在这个方法前后添加代码,但是不改动原有代码,知道这个方法执行时间。就是知道每次它sleep多少时间。

我们先生成一个Handler 统一代理接口叫 invocationHandler 实现类叫 TimeHandler,就是用于添加时间的Handler。

接口类:
import  java.lang.reflect.Method;
public  interface  InvocationHandler {
      public  void  invoke(Object  o ,Method  m );
}
接口有个invoke方法。

TimeHandler实现类:
import  java.lang.reflect.InvocationTargetException;
import  java.lang.reflect.Method;

public  class  TimeHandler  implements  InvocationHandler {
      private  Object  target ;
     //构造函数
      public  TimeHandler(Object  target ) {
             super ();
             this .  target  =  target ;
     }
     
      @Override
      public  void  invoke(Object  o , Method  m ) {
            long  start  = System. currentTimeMillis();//添加时间记录
           System. out.println( "start time:" +  start );
             try  {
                  m .invoke(  target );
           }  catch  (Exception  e ) {
                  e .printStackTrace();
           }
             long  end  = System. currentTimeMillis();//添加时间记录
           System.  out .println(  "time:"  + (  end -  start ));
     }
}

上面代码的意思:
这个实现类,实现了一个接口InvocationHandler,并重写了它的invoke方法 这个方法 利用java反射机制将传入的m方法,属于Method类(反射中的Method类),对传进来的这个target对象的方法,添加记录时间的代码。


代码里面调用反射 Method类的invoke方法得到需要的被处理的对象的方法。这个m即传如的未知的方法。
这个例子中,即通过   m .invoke(   target );调用tank对象的move方法。后面会调用。 
注意说明:
重写的invoke方法和上面的反射函数的invoke不是一个方法。
重写的invoke 方法的第一个参数Object o在这个例子中没有用到。在java源代码里面有用到(先不用管)。
重写的invoke 方法的第二个参数就是Method 的m。
invoke会被循环调用,因为一个实体类中可以有很多方法,这个例子中target是tank,而tank对象下面只有一个move方法。

我们在invoke处理的时候,target就是指定的传递进来的对象。我们回到期初的代码就可以知道。
     Tank  t  =  new  Tank ();
     InvocationHandler  h  =  new  TimeHandler(  t );
生成一个Tank 对象,把tank对象传进去。invoke tank这个target对象的m方法。

现在基本的使用的原理就完成了。
Moveable  m  = (Moveable)Proxy.newProxyInstance(Moveable.  class ,  h );    
当我们执行这条语句的时候,newProxyInstance方法 就会通过第一个参数Moveable.class 获得这个Tank对象 override的所有方法名,利用这些方法名会去找第二个参数h (就是TimeHandler)下面调用invoke方法,把这些方法名逐一循环放进invoke方法里面去。这样我们就把tank下面的方法在TimeHandler里面添加了代理。

最后newProxyInstance 帮我们生成对象返回给我们。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自动控制节水灌溉技术的高低代表着农业现代化的发展状况,灌溉系统自动化水平较低是制约我国高效农业发展的主要原因。本文就此问题研究了单片机控制的滴灌节水灌溉系统,该系统可对不同土壤的湿度进行监控,并按照作物对土壤湿度的要求进行适时、适量灌水,其核心是单片机和PC机构成的控制部分,主要对土壤湿度与灌水量之间的关系、灌溉控制技术及设备系统的硬件、软件编程各个部分进行了深入的研究。 单片机控制部分采用上下位机的形式。下位机硬件部分选用AT89C51单片机为核心,主要由土壤湿度传感器,信号处理电路,显示电路,输出控制电路,故障报警电路等组成,软件选用汇编语言编程。上位机选用586型以上PC机,通过MAX232芯片实现同下位机的电平转换功能,上下位机之间通过串行通信方式进行数据的双向传输,软件选用VB高级编程语言以建立友好的人机界面。系统主要具有以下功能:可在PC机提供的人机对话界面上设置作物要求的土壤湿度相关参数;单片机可将土壤湿度传感器检测到的土壤湿度模拟量转换成数字量,显示于LED显示器上,同时单片机可采用串行通信方式将此湿度值传输到PC机上;PC机通过其内设程序计算出所需的灌水量和灌水时间,且显示于界面上,并将有关的灌水信息反馈给单片机,若需灌水,则单片机系统启动鸣音报警,发出灌水信号,并经放大驱动设备,开启电磁阀进行倒计时定时灌水,若不需灌水,即PC机上显示的灌水量和灌水时间均为0,系统不进行灌水。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值