前言
在开始这个实践之前,我们应该首先明白以下几个问题:
1.什么是代理模式?
2.为什么要使用它?
3.怎么使用它?
4.它的原理是什么?
什么是代理模式?
代理模式是对象的结构模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
所谓代理,就是一个人或者机构代表另一个人或者机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式类图如下:
在代理模式中的概念:
● 抽象接口:代理类和委托类的共同接口,提供业务逻辑的声明。
● 代理类:代理类负责转发消息给委托类、并对委托类的访问进行控制
● 委托类:又被称为被代理类,负责具体业务逻辑的实现。
为什么要使用它?
使用代理模式创建代理对象,让代理对象控制目标对象的访问(目标对象可以是远程的对象、创建开销大的对象或需要安全控制的对象),并且可以在不改变目标对象的情况下添加一些额外的功能。
怎么使用它?
根据程序运行时,代理类是否存在将代理分为静态代理和动态代理。
静态代理的使用如下:
抽象接口,负责具体业务声明
public interface IFactory {
void SellProduct();
}
委托类,负责具体业务的实现
public class FoodFactory implements IFactory{
@Override
public void SellProduct() {
System.out.print("sell food product");
}
}
代理类,负责控制委托类对象的访问
public class ProxyFactory implements IFactory {
private IFactory factory;
public ProxyFactory(IFactory factory) {
this.factory = factory;
}
@Override
public void SellProduct() {
//这里可以增加一些条件的判断,来控制对委托对象的访问
factory.SellProduct();
}
}
Junit单元测试
@Test
public void testStaticProxy() {
//静态代理测试
IFactory factory = new FoodFactory();
ProxyFactory proxyFactory = new ProxyFactory(factory);
proxyFactory.SellProduct();
}
分析:由上述代码可以看出,委托类FoodFactory只关注业务本身,代理类ProxyFactory的使用隐藏了业务具体实现,使得业务的重用性更高;然而在现实开发过程中,这种实现是非常少见的,一般情况,业务类会是多个接口的实现,而代理的过程中也需要实现这些接口,且根据不同业务封装,可能就会产生多个代理类而这时又因为功能需求,不得不访问这些接口的时候,这种代理方式就显得捉襟见肘了;这些情况下,就需要引用动态代理来解决了.
动态代理
在这里就利用动态代理来实现界面之间的跳转与传值,希望可以帮助大家更好的更透彻的理解动态代理的使用场景.
为了实现动态代理,要引入相关的类和接口 java.lang.reflect.Proxy 提供了一系列的static方法,用来创建代理类或对象,这个类是所有动态代理类的父类以及java.lang.reflect.InvocationHandler(调用处理器接口,只有一个invoke方法,处理动态代理类对象方法的调用,每个动态代理类都会关联一个InvocationHandler).
下面是对方法的介绍
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,InvocationHandler h)
-ClassLoader loader // 被代理类的类加载器,用来创建代理类
- Class<?>[] interfaces //被代理类实现的接口,创建的代理类会实现这些接口
- InvocationHandler invocationHandler //最关键的接口!它只有一个 invoke 方法,是代理类进行 拦截操作 的入口,一般需要自定义一个 Handler 来实现方法增强。
public Object invoke(Object proxy, Method method, Object[] args)
proxy 就是上面通过Proxy.newProxyInstance生成的对象proxy
method 是proxy的调用的任何方法
args 是method的参数
接下来我们实现动态代理
(1)编写抽象接口,声明activity之间的跳转
public interface Jumper {
@ActivityInfo(clz = NoParametersActivity.class)
IntentHandler gotoNoParametersActivity();
@ActivityInfo(clz = ParametersActivity.class)
IntentHandler gotoParametersActivity(@Extra(value = "param",author = "authorName")String userName);
}
(2)生成动态代理对象jumper
最重要的业务拦截处理在InvocationHandler中处理
(3)调用方法实现页面跳转并传参
jumper.gotoParametersActivity("15010").startActivity(this);
(4)在跳转页面获取值
只需要上面四步就可实现跳转,稍后我会奉上源码.
动态代理的实现原理
不说话, 直接附上源码,更好的理解动态代理机制
下面这段代码引入了(http://paddy-w.iteye.com/blog/841798)博客中的片段。
public final class $Proxy0 extends Proxy implements Subject {
private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2;
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals",
new Class[] { Class.forName("java.lang.Object") });
m0 = Class.forName("java.lang.Object").getMethod("hashCode",
new Class[0]);
m3 = Class.forName("***.RealSubject").getMethod("request",
new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString",
new Class[0]);
} catch (NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
} catch (ClassNotFoundException classnotfoundexception) {
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
} //static
public $Proxy0(InvocationHandler invocationhandler) {
super(invocationhandler);
}
@Override
public final boolean equals(Object obj) {
try {
return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })) .booleanValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public final int hashCode() {
try {
return ((Integer) super.h.invoke(this, m0, null)).intValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final void request() {
try {
super.h.invoke(this, m3, null);
return;
} catch (Error e) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public final String toString() {
try {
return (String) super.h.invoke(this, m2, null);
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}
这个类的生成最终是在Proxy中是在通过native方法Proxy.generateProxy生成类的字节码,再经过ClassLoader加载,就像class文件就被加载的过程,然后用newInstance方式生成最终的Proxy对象,具体的细节可以自行查看源码.
上面的$Proxy0就是生成的动态代理类,看到上面就明白代理类对方法的调用是怎么与InvocationHandler中invoke()方法关联的了,至此分析结束.
android中使用动态代理实现界面跳转传值demo下载地址: