Java基本六:代理

来源:互联网 发布:程序员大神是什么样子 编辑:程序博客网 时间:2024/06/06 00:05

            

           代理其实理解起来很简单,就是代理者代理被代理者去做完成一些事情,并且增加一些自己附加的行为。比如将军下达命令到士兵,那么将军肯定不是亲自去士兵面前然后命令,而是找人传达命令到士兵面前。士兵执行命令。暂且将这个传达命令的人员称为传达员bellman。这就是代理的一个例子。传达员代理将军执行命令。

            在Java中有静态代理和动态代理。动态代理又有jdk、cglib、Javassist、asm等。动态代理只说jdk代理。

            静态代理就是我们写好的代理类进行代理。

            静态代理           

         士兵类:

         public class Soldier {


protected String name;
protected int age;
protected String gunName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGunName() {
return gunName;
}
public void setGunName(String gunName) {
this.gunName = gunName;
}
public void shoot(){
       System.out.println(age+"岁的"+name+"拿着"+gunName+"射击");
   }
public void run(){
System.out.println(age+"岁的"+name+"拿着"+gunName+"跑步");
}
}  

         海军士兵

           public class SeaSoldier extends Soldier{


    public void sail(){
        System.out.println(age+"岁的"+name+"开船");
    }


    @Override
    public void shoot() {
        // TODO Auto-generated method stub
        System.out.println(age+"岁的"+name+"在水下拿着"+gunName+"射击");
    }
}

             将军类:

             public class General extends Soldier implements Commander{

private int level;

   public int getLevel() {
       return level;
   }

   public void setLevel(int level) {
       this.level = level;
   }
 
   @Override
   public void executeCommand(Command command) {
       // TODO Auto-generated method stub


      System.out.println(age+"岁的"+name+"命令:");      
       command.commandExcute();
   }
}

         

           命令者接口:

          public interface Commander {

void executeCommand(Command command);
        }

          命令接口:

            public interface Command {

void commandExcute();
       }

         跑路命令类:

public class Run implements Command{


    
    private Soldier soldier;
    
    public Run(Soldier soldier) {
        super();
        this.soldier = soldier;
    }


    public Soldier getSoldier() {
        return soldier;
    }


    public void setSoldier(Soldier soldier) {
        this.soldier = soldier;
    }


    @Override
    public void commandExcute() {
        // TODO Auto-generated method stub
        System.out.println(soldier.name+"执行命令");       
         soldier.run();
        
    }


}

         那么需要声明一个传达员类来代理将军执行命令,也就是代理命令者执行命令。

         那么可以这样写:

        public class BellMan implements Commander{


private Commander commander;
public BellMan(Commander commander) {
// TODO Auto-generated constructor stub
this.commander=commander;
}
public BellMan() {
// TODO Auto-generated constructor stub
}
public void setCommander(Commander commander) {
this.commander = commander;
}
@Override
public void executeCommand(Command command) {
// TODO Auto-generated method stub
System.out.println("命令之开始时间:"+System.currentTimeMillis());
commander.executeCommand(command);
System.out.println("命令之结束时间:"+System.currentTimeMillis());
}

}

        传达员代理执行命令,并且还需要监视命令执行,上报完成情况。这里完成的情况,就打印处理。不仅仅是将军的命令,传达员可以代理执行,其它上级的命令,传达员都可以代理执行,并且监视上报命令完成情况。这样代理的好处就是命令者只关注命令本身,其它的统一的操作,都可以交给代理者进行完成。不必每一个命令者都需要亲自去完成监视和上报命令的执行情况。

          这样的设计也是方便扩展,修改。如果交给命令者去完成监视的行动,那么监视的方式变了,需要去修改每一个命令者的方法,这样不易于修改。代理者模式,只需要去修改代理者的方法就可以 完成对所有命令者的那么其余的行为的修改了。


          

          测试执行:

  Soldier soldier=new Soldier();
soldier.setName("小明");soldier.setAge(18);soldier.setGunName("手枪");
Command command=new Run(soldier);
General general=new General();
general.setName("威灵顿");general.setAge(55);general.setGunName("手枪");general.setLevel(2);
BellMan bellMan=new BellMan(general);
bellMan.executeCommand(command);


                这些代码中也结合了命令者模式,

              士兵可以有好多种士兵,命令也是可以是好多种命令,命令者仍然是可以是将军或者其它高级的将领。那么传达员只关注命令者接口,来代理执行命令。

              动态代理

               Java的动态代理,是运行时修改对象的内容,对对象的方法等进行重写,改变。这仅仅是个人理解。

               

               代理生成对象:

               import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


public class ProCommander implements InvocationHandler{




private Commander commander;
public void setCommander(Commander commander) {
this.commander = commander;
}
public ProCommander(Commander commander) {
// TODO Auto-generated constructor stub
this.commander=commander;
}

public Commander getProxyCommander() {

return (Commander) Proxy.newProxyInstance(commander.getClass().getClassLoader(), commander.getClass().getInterfaces(), this);

}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
System.out.println("命令之开始时间:"+System.currentTimeMillis());
Object invoke = method.invoke(commander, args);
System.out.println("命令之结束时间:"+System.currentTimeMillis());
return invoke;
}
}

                 可以看出实现了InvocationHandler接口,这个接口就是来处理代理的其它操作的。实现invoke方法。最后获取代理对象,由Proxy对象生成一个新的代理实例,传入对象的类加载器和对象的接口数组,又传入这个代理类处理操作的接口。


                  测试执行:

               Soldier soldier=new Soldier();
soldier.setName("小明");soldier.setAge(18);soldier.setGunName("手枪");
Command command=new Run(soldier);
General general=new General();
general.setName("威灵顿");general.setAge(55);general.setGunName("手枪");general.setLevel(2);
ProCommander proCommander=new ProCommander(general);
Commander commander = proCommander.getProxyCommander();
commander.executeCommand(command);

               执行的结果和静态代理的执行结果是一样的。

                代理生成对象,又可以被称为拦截器。拦截一个方法,在方法执行前和执行后都可以进行一系列的操作。

                这样的话,拦截器可以拦截一切对象的的方法,那么拦截器可以这样改:

              拦截方法接口:

             public interface InterceptorMothod {

void before();
void after();
          }

                代理类:

                import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


public class ProxyObject implements InvocationHandler{


private Object object;
private InterceptorMothod interceptorMothod;
public void setInterceptorMothod(InterceptorMothod interceptorMothod) {
this.interceptorMothod = interceptorMothod;
}
public void setCommander(Object object) {
this.object = object;
}
public ProxyObject(Object object) {
// TODO Auto-generated constructor stub
this.object=object;
}

public Object getProxyCommander() {

return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);

}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
interceptorMothod.before();
Object invoke = method.invoke(object, args);
interceptorMothod.after();
return invoke;
}
}

       这样就对所有的类的方法进行了拦截。进行了其它的额外的方法执行。如果想对特殊的方法进行拦截,那么也简单,只需要判断对象的类名和方法的名字就可以拦截。

       代理有什么用呢?用处多了,日志、跟踪、验证等。在spring 的beans 中的aop的配置就是这个代理的配置。这里只是简单的写了原理,类的拦截,包的拦截,方法的拦截,这里没做过多的说明。

     

           






1 0
原创粉丝点击