A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 血马雄风 中级黑马   /  2015-8-26 10:20  /  200 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

代理

技术要点:1、使用接口规范代理类和被代理类的行为
          2、通过使用代理类实现对被代理类的调用

解决问题:整体-部分
         
public interface ActionInterf{
    boolean open();
    boolean close();  
}

public class Door implements ActionInterf{
    private isClose = ture;
    public boolean open(){
        if(isClose) isClose = false;
        return isClose;        
    }
   
    public boolean close(){
        if(!isClose) isClose = ture;
        return isClose;        
    }   
}

//proxy
public class House implements ActionInterf{
    private ActionInterf proxied = new Door();     //这里只能代理Door
    public boolean openDoor(){
        return proxied.open();        
    }
   
    public boolean close(){
        return proxied.closeDoor();      
    }        
}

//main
House house = new House();
house.open();
house.close();


动态代理

技术要求:我(代理类)能够代理所有需要代理的类(具有某种行为规范的所有具体实现类),并能够调用相应的方法

技术要点:1、通过动态传入需要代理的类

解决问题:根据实际需要,代理所希望代理的具体类

public class Window implements ActionInterf{
    private isClose = ture;
    public boolean open(){
        if(isClose) isClose = false;
        return isClose;        
    }
   
    public boolean close(){
        if(!isClose) isClose = ture;
        return isClose;        
    }   
}

//dynamicProxy
public class DynamicProxyHouse implements ActionInterf{
    private ActionInterf proxied;     //代理所有需要代理的类
    public void DynamicHouse(){}
    public setProxied(ActionInterf proxied){ this.proxied = proxied;}
    public boolean open(){
        return proxied.open();        
    }
   
    public boolean close(){
        return proxied.close();      
    }        
}

//main
DynamicProxyHouse proxyHouse = new DynamicProxyHouse();
proxyHouse.setProxied(new Door());
proxyHouse.open();
proxyHouse.close();
proxyHouse.setProxied(new Window());
proxyHouse.open();
proxyHouse.close();


反射代理

技术要点:1、使用Java的反射机制
          2、使用Java提供的Proxy类
          3、实现Java的InvocationHandler接口或其某一个子类

解决问题:使用反射机制实现动态代理,实现将所有调用重定向到调用处理器。同时,我们不需要实现代理类,简化了工作。


class DynamicProxyHandler implements InvocationHandler{    //能不能使用泛型
    private  Object proxied;
    public void DynamicProxyHandler(Object proxied){this.proxied = proxied;}
    public Object invoke(Object proxy, Method method, Object[] args){
        //proxy用来区分请求的来源,但大多情况我们并不需要关心,即proxy没有用
        //...
        return method.invoke(proxied, args);
    }   
}

//main
//方法一:
DynamicProxyHandlerDoor doorHandler = new DynamicProxyHandler(new Door());
//proxy的Class
Class proxyClass = Proxy.getProxyClass(ActionInterf.class.getClassLoader(), //类加载器
                                         new Class[]{ActionInterf.class});  //代理类要实现的接口列表
//proxy的实例
ActionInterf proxyDoor = (Door)proxyClass.getConstructor(new Class[]{InvocationHandler.class}
                               ).newInstance(new Object[]{doorHandler});
proxyDoor.open();    //去调用invoke()
proxyDoor.close();


//方法二:最好使用这种方式
DynamicProxyHandlerDoor = new DynamicProxyHandler(new Door());
ActionInterf proxyDoor = (ActionInterf)Proxy.newProxyInstance(
                                ActionInterf.class.getClassLoader(),
                                  new Class[]{ActionInterf.class},  //代理类要实现的接口列表
                                    DynamicProxyHandlerDoor);       //指定调用处理程序  
proxyDoor.open();    //去调用invoke()
proxyDoor.close();



反射代理实现原理:猜测
Proxy.newProxyInstance()
      编译器首先创建一个相应接口的代理类ProxyActionInterf,
      class ProxyActionInterf{
          InvocationHandler handler = null;
          void ProxyActionInterf(InvocationHandler handler){ this.handler = handler;}
          public boolean open(){
              handler.invoke(this, handler.getProxied().getClass().getDecriXXXXMethod("open", null), args);
              
          }
          ...
      }

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马