动态代理(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 帮我们生成对象返回给我们。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值