java静态代理和动态代理

来源:互联网 发布:gartner 云计算 2017 编辑:程序博客网 时间:2024/05/19 02:25

1.  java代理静态代理和动态代理:

静态代理 

 package onlyfun.caterpillar;

 

import java.util.logging.Level;

import java.util.logging.Logger;

 

public classHelloSperker {

   private Loggerlogger = Logger.getLogger(this.getClass().getName());

  

   public void hello(String name){

      //方法执行开始时留下记录

      logger.log(Level.INFO,"hello method starting ...");;

     

      System.out.println("name: "+name);

     

      //方法结束时留下记录

      logger.log(Level.INFO,"hello method ending ...");

     

   }

   public static void main(String []args){

      HelloSperkerhelloSperk= newHelloSperker();

      helloSperk.hello("adu");

   }

}

如果分析这段代码,当执行hello时在方法开始和结束都进行相应的记录,最简单的方法就是如上面使用日志动作,然而对于HelloSperker来说,日志的这几个动作并不属于它的业务逻辑,因此是给HelloSperker增加了额外的工作。

如果有大量的类似的程序,里面都需要进行与业务无关的日志记录、权限检查、事务管理等,而且如果要维护这些代码,如果仍然是这样写法,维护必要要耗费大量时间,负担不可谓不重啊。而且这样的代码,如果哪一天不需要相关的日志等服务了,那么修改也会让我们很痛苦。如何解决这样令我们痛苦的事情那?

一个好的方法就是使用代理proxy。代理可分为静态代理和动态代理。

静态代理:在静态代理中,代理对象与被代理对象必须实现同一个接口,在代理对象中可以实现日志等相关服务,并在需要的时候再调用被代理的对象,被代理对象当中就可以仅保留与业务相关的职责。

例子:

#Interface:IHello

package onlyfun.caterpillar;

 

public interfaceIHello {

public voidhell(String name);

}

#Class:HelloSperker1 :implements IHello

package onlyfun.caterpillar;

 

public classHelloSperker1 implements IHello {

 

   @Override

   public void hell(String name) {

      // TODO Auto-generated method stub

      System.out.println("name:"+name);

   }

 

}

#class:HelloProxy:implements IHello

package onlyfun.caterpillar;

 

import java.util.logging.Level;

import java.util.logging.Logger;

 

public classHelloProxy implementsIHello {

   private Loggerlogger = Logger.getLogger(this.getClass().getName());

   private IHellohelloObject;

   public HelloProxy(IHellohelloObject){

      this.helloObject =helloObject;

   }

   @Override

   public void hell(String name) {

      // TODO Auto-generated method stub

      log("hello method starting ....");

      helloObject.hell(name);

      log("hello method ending ...");

   }

   public void log(String msg){

      logger.log(Level.INFO,msg);

   }

}

#StaticProxyTest

package onlyfun.caterpillar;

 

public classStaticProxyTest {

 

   public static void main(String[] args) {

      // TODO Auto-generated method stub

      IHellohelloObject  = new HelloSperker1();

      HelloProxyproxy= newHelloProxy(helloObject);

      proxy.hell("along");

   }

 

}

这里确实是将业务和与业务无关的内容分开了,比较之前确实是有较大改善,但是如果这样每个业务类都需要对应一个这样的proxy,那也是工作量巨大,有没有更好的方式那。

自己的说明:这里代理类可以不实现IHello接口,只不过在该代理类内部写一个一样的方法,即可,只不过不是实现,貌似也能实现效果。有点像设计模式里的门面模式(装饰模式)吧。

下面将动态代理:

   在jdk1.3之后加入了可协助开发动态代理功能的API,使用动态代理,因此可以使用一个handler处理服务于各个对象,但是这个处理者的类handler必须实现java.lang.reflect.InvocationHandler接口。

具体的实现是:

package onlyfun.caterpillar;

 

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.util.logging.Level;

import java.util.logging.Logger;

 

public classLogHandler implementsInvocationHandler {

   private Loggerlogger = Logger.getLogger(this.getClass().getName());

   //声明一个代理对象

   private Objectdelegate;

   //绑定该代理对象,返回一个代理,期间需要指定所要代理的接口

   public Object bind(Objectdelegate){

      this.delegate  =delegate;

      return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),

                              delegate.getClass().getInterfaces(),

                              this);

   }

//重写invoke方法(使用代理时每次操作都会执行的方法,实际上执行的是

//method.invoke,在它前后加上日志动作即可)

   @Override

   public Object invoke(Objectproxy, Method method, Object[]args) throws Throwable {

      // TODO Auto-generated method stub

      Objectresult  =null;

      try{

         log("method starts: ....["+method+"]...");

         result  =method.invoke(delegate,args);

         log("method end:...["+method+"]...");

      }catch(Exceptione){

         log(e.toString());

        

      }

      return result;

   }

   public void log(String msg){

      logger.log(Level.INFO,msg);

   }

}

#动态代理测试

package onlyfun.caterpillar;

 

public classProxyDemo {

 

   public static void main(String[] args) {

      // TODO Auto-generated method stub

//初始化动态代理handler对象

      LogHandlerlogHandler= newLogHandler();

//绑定需要被代理的对象实例,并返回一个代理对象,

      IHello  helloSperk = (IHello)logHandler.bind(new HelloSperker1());

//执行输出

      helloSperk.hell("dudu");

   }

 

}

 

这里可以看出LogHandler不在执行与特定的接口,这里根据指定的接口代替了原来静态代理中的实现接口的方式,从而达到通用。这种从单独设计,到使用静态代理,再到使用动态代理,逐层精进、业务独立,达到设计上的复用、可维护性的特征,正是设计的发展方向。

0 0