简介
为其他对象提供一种代理以控制对这个对象的访问。某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以再两者之间起到中介作用。运行阶段才指定代理哪个对象
-
静态代理
Subject 类
public interface Subject {
public void sayGoodBye();
public void sayHello(String str);
}
RealSubject 类
public class RealSubject implements Subject{
@Override
public void sayGoodBye() {
Log.d("zkq","RealSubject sayGoodBye");
}
@Override
public void sayHello(String str) {
Log.d("zkq","RealSubject sayHello " + str);
}
}
ProxySubject 类
public class ProxySubject implements Subject{
private Subject subject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public void sayGoodBye() {
//代理类,功能的增强
Log.d("zkq","ProxySubject sayGoodBye begin");
//在代理类的方法中 间接访问被代理对象的方法
subject.sayGoodBye();
Log.d("zkq","ProxySubject sayGoodBye end");
}
@Override
public void sayHello(String str) {
//代理类,功能的增强
Log.d("zkq","ProxySubject sayHello begin");
//在代理类的方法中 间接访问被代理对象的方法
subject.sayHello(str);
Log.d("zkq","ProxySubject sayHello end");
}
}
在mainActivity中调用
public void onStaticClick(View view) {
//被代理的对象,某些情况下 我们不希望修改已有的代码,我们采用代理来间接访问
RealSubject realSubject = new RealSubject();
//代理类对象
ProxySubject proxySubject = new ProxySubject(realSubject);
//调用代理类对象的方法
proxySubject.sayGoodBye();
Log.d("zkq", "******");
proxySubject.sayHello("Test");
}
在调用RealSubject 的方法时候,同步调用了RealSubject 中的方法
log日志
D/zkq: ProxySubject sayGoodBye begin
D/zkq: RealSubject sayGoodBye
D/zkq: ProxySubject sayGoodBye end
D/zkq: ******
D/zkq: ProxySubject sayHello begin
D/zkq: RealSubject sayHello Test
D/zkq: ProxySubject sayHello end
-
动态代理
我们会用到InvocationHandler类,具体怎么使用,可以参考https://blog.csdn.net/yaomingyang/article/details/80981004
在这里我们实现InvocationHandler,修改invoke方法,是他调用我们传入进来的subject
public class SubjectInvocationHandler implements InvocationHandler {
//这个就是我们要代理的真实对象
private Object subject;
public SubjectInvocationHandler(Object subject) {
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在代理真实对象前我们可以添加一些自己的操作
Log.d("zkq","before Method invoke");
Log.d("zkq","Method:" + method);
method.invoke(subject,args);
//在代理真实对象后我们也可以添加一些自己的操作
Log.d("zkq","after Method invoke");
return null;
}
}
在mainActivity中调用,我们传入SubjectInvocationHandler 中一个RealSubject,使得在调用subject.sayGoodBye()的时候,会同步调用RealSubject中的sayGoodBye
public void onProxyClick(View view) {
Subject realSubject = new RealSubject();
SubjectInvocationHandler handler = new SubjectInvocationHandler(realSubject);
//生成代理类
Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(),realSubject.getClass().getInterfaces(), handler);
//输出代理类对象
Log.d("zkq", "Proxy : " + subject.getClass().getName());
Log.d("zkq", "Proxy super : " + subject.getClass().getSuperclass().getName());
Log.d("zkq", "Proxy interfaces : " + subject.getClass().getInterfaces()[0].getName());
//调用代理类sayGoodBye方法
subject.sayGoodBye();
Log.d("zkq", "--------");
//调用代理类sayHello方法
subject.sayHello("Test");
}
-
我们使用动态代理实现下面方法
// Button button3 = findViewById(R.id.button3);
// button3.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// Toast.makeText(MainActivity.this, "点击事件", Toast.LENGTH_SHORT).show();
// }
// });
我们动态修改onClick中的方法,使他调用mainActivity中的test()方法
public void test(){
Toast.makeText(this, "代理的toast", Toast.LENGTH_SHORT).show();
}
接下来就是实现方式
首先是ListenerInvocationHandler类
public class ListenerInvocationHandler implements InvocationHandler {
private Object activity;
private Method activityMethod;
public ListenerInvocationHandler(Object activity, Method activityMethod) {
this.activity = activity;
this.activityMethod = activityMethod;
}
/**
*按钮点下去就执行这个方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return activityMethod.invoke(activity);
}
}
然后是Mainactivity中的实现方法
try {
//获得MainActivity中的test方法
Method test = getClass().getMethod("test");
//通过代理,调用当前MainActivity中的test方法
ListenerInvocationHandler listenerInvocationHandler = new ListenerInvocationHandler(this, test);
View.OnClickListener proxy= (View.OnClickListener)Proxy.newProxyInstance(View.OnClickListener.class.getClassLoader(), new Class[]{View.OnClickListener.class}, listenerInvocationHandler);
//获得button03的setOnClickListener方法 View.OnClickListener.class是setOnClickListener方法的参数
Method onClickMethod = button3.getClass().getMethod("setOnClickListener", View.OnClickListener.class);
//执行setOnClickListener方法 button3.setOnClickListener proxy是传入setOnClickListener中的参数
onClickMethod.invoke(button3, proxy);
} catch (Exception e) {
e.printStackTrace();
}
当点击测试代理时候就是调用的test方法中的test方法了
demo下载地址:demo