Android 静态代理和动态代理
代理模式定义:为其他对象提供一种代理以控制这个对象的访问
静态代理
静态代理比较简单,看下下面的代码就很好理解
//定义一个接口
public interface Subject {
void sayGoodBye();
void sayHello(String str);
}
//定义一个被代理的类
public class RealSubject implements Subject {
@Override
public void sayGoodBye() {
System.out.println("RealSubject sayGoodBye");
}
@Override
public void sayHello(String str) {
System.out.println("RealSubject sayHello " + str);
}
}
//代理类
public class ProxySubject implements Subject {
private Subject subject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public void sayGoodBye() {
//代理类,功能的增强
System.out.println("ProxySubject sayGoodBye begin");
//在代理类的方法中 间接访问被代理对象的方法
subject.sayGoodBye();
System.out.println("ProxySubject sayGoodBye end");
}
@Override
public void sayHello(String str) {
//代理类,功能的增强
System.out.println("ProxySubject sayHello begin");
//在代理类的方法中 间接访问被代理对象的方法
subject.sayHello(str);
System.out.println("ProxySubject sayHello end");
}
}
使用方法
//被代理对象,某些情况,我们不希望修改已有代码,我们采用代理来间接访问
RealSubject realSubject = new RealSubject();
//代理类对象
ProxySubject proxySubject = new ProxySubject(realSubject);
proxySubject.sayGoodBye();
proxySubject.sayHello("Test");
输出结果
ProxySubject sayGoodBye begin
RealSubject sayGoodBye
ProxySubject sayGoodBye end
ProxySubject sayHello begin
RealSubject sayHello Test
ProxySubject sayHello end
动态代理
动态代理也叫做jdk代理、接口代理,不需要实现目标对象的接口。生成代理对象,使用的是Java的API,动态的在内存中构建代理对象。
1、在java的动态代理机制中,有两个重要的类或接口
一个是 InvocationHandler(Interface)
另一个则是Proxy(Class)
这一个类和接口是实现我们动态代理所必须用到的
2、 InvocationHandler
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
proxy:指代生成的代理对象;
method:指代的是我们所要调用真实对象的某个方法的Method对象;
args:指代的是调用真实对象某个方法时接受的参数;
每一个代理实类例的invocation handler都要实现InvocationHandler这个接口。并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke 方法来进行调用
3、 Proxy这个类的 newProxyInstance 这个方法
JDK动态代理需要借助接口来实现,如果我们要代理的对象功能没有抽成任何接口,那么我们就无法通过JDK动态代理的方式来实现。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上。
第一步:定义一个接口
//定义一个接口
public interface Subject {
void sayGoodBye();
void sayHello(String str);
}
第二步:定义真是对象(被代理类):
//定义一个被代理的类
public class RealSubject implements Subject {
@Override
public void sayGoodBye() {
System.out.println("RealSubject sayGoodBye");
}
@Override
public void sayHello(String str) {
System.out.println("RealSubject sayHello " + str);
}
}
第三步: 定义一个InvocationHandler, 相当于一个代理处理器
SubjectInvocationHandler并不是真正的代理类,而是用于定义代理类需要扩展、增强那些方法功能的类。在invoke函数中,对代理对象的所有方法的调用都被转发至该函数处理。在这里可以灵活的自定义各种你能想到的逻辑。
public class SubjectInvocationHandler implements InvocationHandler {
//这个就是我们要代理的真实对象
private Object subject;
//构造方法,给我们要代理的真实对象赋初值
public SubjectInvocationHandler(Object subject) {
this.subject = subject;
}
@Override
public Object invoke(Object object, Method method, Object[] args) throws Throwable {
//在代理真实对象前我们可以添加一些自己的操作
System.out.println("before Method invoke");
System.out.println("Method:" + method);
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(subject, args);
//在代理真实对象后我们也可以添加一些自己的操作
System.out.println("after Method invoke");
return null;
}
}
第四步:调用
//被代理类
Subject realSubject = new RealSubject();
//我们要代理哪个类,就将该对象传进去,最后是通过该被代理对象来调用其方法的
SubjectInvocationHandler handler = new SubjectInvocationHandler(realSubject);
//生成代理类
Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(), handler);
//输出代理类对象
System.out.println("Proxy : "+ subject.getClass().getName());
System.out.println("Proxy super : "+ subject.getClass().getSuperclass().getName());
System.out.println("Proxy interfaces : "+ subject.getClass().getInterfaces()[0].getName());
//调用代理类sayGoodBye方法
subject.sayGoodBye();
System.out.println("--------");
//调用代理类sayHello方法
subject.sayHello("Test");
结果:
Proxy super : java.lang.reflect.Proxy
Proxy interfaces : com.company.ha.Subject
before Method invoke
Method:public abstract void com.company.ha.Subject.sayGoodBye()
RealSubject sayGoodBye
after Method invoke
--------
before Method invoke
Method:public abstract void com.company.ha.Subject.sayHello(java.lang.String)
RealSubject sayHello Test
after Method invoke
总结:
与静态代理相比,动态代理具有如下的优点:
1.代理转发的过程自动化了,实现自动化搬砖;
2.代理类的代码逻辑和具体业务逻辑解耦,与业务无关;