android 代理模式 动态代理

本文深入探讨了Android开发中的代理模式,特别是动态代理的概念、优势及其实现机制。文章详细介绍了动态代理的工作原理,包括如何利用Proxy类和InvocationHandler接口创建动态代理实例。

android 代理模式 动态代理

代理模式:
代理模式为另一个对象提供一个代理以控制对这个对象的访问,它分动态代理、静态代理。

代理优点:
1、隐藏被代理类的实现;
2、实现与被代理类的解耦,在不修改被代理类代码的情况下能够做一些额外的处理

静态代理:
代理类中的方法,都指定地调用被代理类中对应的方法,代理类所做的事情就是调用触发被代理类中对应的方法
通常情况下,静态代理中的代理类和被代理类会实现同一接口或是派生自相同的父类(静态代理的局限在于运行前必须编写好代理类)
示例:

public interface Sell { 
   void sell(); 
} 
public class Vendor implements Sell { 
   public void sell() {
      System.out.println("sell");
   } 
} 
public class VendorAgent implements Sell {  
   private Vendor mVendor;   //静态代理可以通过聚合来实现,让代理类持有一个被代理类的引用
   public VendorAgent(Vendor vendor) {  
      mVendor = vendor;   
   }    
   public void sell() { 
      if(isCollegeStudent()) {
        mVendor.sell();
      }
   } 
}

动态代理
代理类在程序运行时创建的代理方式,代理类并不是在Java代码中定义的,而是在运行时根据在Java代码中的“指示”动态生成的。
相比于静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。
它将自己方法功能的实现交给InvocationHandler角色,外界对Proxy角色中每一个方法的调用,Proxy角色都会交给InvocationHandler来处理,
而InvocationHandler则调用被代理类的方法

动态代理的原理:
1、首先通过Proxy的newProxyInstance方法获取代理类实例,
2、而后通过这个代理类实例调用代理类的方法,对代理类的方法的调用实际上都会调用中介类
(调用处理器–实现了InvocationHandler接口的类)的invoke方法,
3、在invoke方法中我们调用被代理类的相应方法,并且可以添加自己的处理逻辑

动态代理模式中代理类的生成步骤:
1、获取被代理类上的所有接口列表;
2、确定要生成的代理类的类名,系统默认生成的名字为:
com.sun.proxy.$ProxyXXXX
3、根据需要实现的接口信息,在代码中动态创建该代理类的字节码;
4、将对应的字节码转换为对应的Class对象;
5、创建InvocationHandler的实例对象h(用来处理Proxy角色的所有方法调用);
6、以创建的h对象为参数,实例化一个Proxy角色对象

动态代理涉及到:
InvocationHandler接口
Proxy类

InvocationHandler接口:
在使用动态代理时,需要定义一个位于代理类与被代理类之间的中介类,这个中介类要求实现InvocationHandler接口:
public interface InvocationHandler {
Object invoke(Object proxy, Method method, Object[] args); //当调用代理对象上的一个方法,该方法的调用将被编码并转发到它所关联的调用处理程序的方法
}
实现这个接口的中介类用做“调用处理器”,当调用代理类对象的方法时,这个“调用”会转送到invoke方法中,
proxy: 代理类对象
method:标识了具体调用的是代理类的哪个方法,
args:为method方法的参数。
这样一来,对代理类中的所有方法的调用都会变为对invoke的调用,
这样我们可以在invoke方法中添加统一的处理逻辑(也可以根据method参数对不同的代理类方法做不同的处理)

Proxy类newProxyInstance方法来获取一个代理类实例:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 
    throws IllegalArgumentException 

loader:定义了代理类的ClassLoder;
interfaces:代理类实现的接口列表
h:调用处理器,实现了InvocationHandler接口的代理类实例
函数原型:

public static Object newProxyInstance(ClassLoader loader, Class<?>[]interfaces,InvocationHandler h) throws IllegalArgumentException { 
    if(h == null) { 
        throw new NullPointerException(); 
    } 
    Class cl = getProxyClass(loader, interfaces);  //获得与指定类装载器和一组接口相关的代理类类型对象
    try{ 
        Constructor cons = cl.getConstructor(constructorParams);  //通过反射获取构造函数对象并生成代理类实例
        return (Object) cons.newInstance(new Object[] { h }); 
    }catch (NoSuchMethodException e) { 
        throw new InternalError(e.toString()); 
    }catch (IllegalAccessException e) { 
        throw new InternalError(e.toString()); 
    }catch (InstantiationException e) { 
        throw new InternalError(e.toString()); 
    }catch (InvocationTargetException e) { 
        throw new InternalError(e.toString()); 
    } 
}

Proxy类的getProxyClass()方法调用了ProxyGenerator的generatorProxyClass()方法去生成动态类:

public static void generateClassFile(Class clazz, String proxyName)
{   
    byte[] classFile = ProxyGenerator.generateProxyClass(proxyName, clazz.getInterfaces()); //根据类信息和提供的代理类名称,生成字节码  
    ...
}

示例:

public interface Sell { 
   void sell(); 
} 
public class Vendor implements Sell { 
   public void sell() {
      System.out.println("sell");
   } 
} 
public class VendorAgent implements InvocationHandler {
   private Vendor mVendor;   
   public VendorAgent(Vendor vendor) {  
      mVendor = vendor;   
   }    
   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       //do something before
       return method.invoke(subject, args);
   }
}

public class Test {
    public static void main(String[] args) {
      Sell sell = new Vendor();
      VendorAgent proxy = new VendorAgent(sell);
      Sell sub = (Sell) Proxy.newProxyInstance(sell.getClass().getClassLoader(), sell.getClass().getInterfaces(), proxy);
      sub.sell();
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值