JAVA 动态代理

Posted by steven on March 30, 2015

代理模式

代理模式是一种常见的设计模式,为其他对象提供一种代理以控制对这个对象的访问。代理类与委托类有同样的接口,代理类负责为委托类预处理,过滤和转发消息,并进行消息被委托类执行之后的逻辑处理

静态代理

开发人员实现代码或使用特定工具生成代码之后编译,在程序运行之前,代理类的class文件以及存在

例:

//接口
public interface Subject {
   public void foo();
}

实际对象

public class RealSubject implements Subject {
    public void foo(){
       System.out.println("RealSubject foo");  
    }     
}

静态代理类

public class SubjectProxy implements Subject {
    Subject subjectImpl = new RealSubject();
    public void foo(){
       subjectImpl.foo();
    }     
}

main:

public static void main(String args[]){
    Subject sub = new SubjectProxy();
    sub.foo();
}

当接口的方法很多时,代理类的代码量将相当大,不便于维护

动态代理

要实现动态代理必须实现InvocationHandler接口,InvocationHandler 只有一个方法:

invoke(Object proxy, Method method, Object[] args)

该方法用来处理被代理实例调用的方法的处理

每个Proxy实例都有一个关联的invocation handler。当代理调用一个方法的时候,该方法被编码发送到InvocationHandler的invoke方法。

public class ProxyHandler implements InvocationHandler{

   //代理委托对象
   private Object tar;

   public ProxyHandler(Object tar){
       this.tar = tar;
   }

   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable  {  
        //调用具体委托对象的方法
        Object returnValue = method.invoke(tar, args);    
        return returnValue;  
    }  
}

使用:

public static void main(String[] args)  {  

   Subject realSubject = new RealSubject();  
   InvocationHandler handler = new ProxyHandler(realSubject);  

    ClassLoader loader = realSubject.getClass().getClassLoader();  
    Class[] interfaces = realSubject.getClass().getInterfaces();  
    /**
     * 创建一个代理类的实例,该代理类将指定接口的方法发送到对应的              
     * InvocationHandler
     */
    Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);  
    subject.foo();    
 }  

在运行时,JDK会生成一个代理类的实例,该代理类继承Proxy类,并实现了 Subject接口。在实现Subject接口方法是的时候,通过JAVA反射机制调用了InvocationHandler的invoke方法。