Java的动态对象代理
个人目前水平的理解,以后有不对会更正
简介
看过p
审文章之后,先给动态对象代理下一个自己能理解到位的定义
就是通过代理接口实现了一个类似于php
的__call
方法
不需要看很多的概念,容易懵圈,什么动静态,直接放弃
我们需要知道的时,如果实现了这么一个代理,当调用这个代理对象的任意方法时,都会触发什么方法就可以了
为此,我找到了一段描输,简单而直白
InvocationHandler
接口是proxy
代理实例的调用处理程序实现的一个接口,每一个proxy
代理实例都有一个关联的调用处理程序;在代理实例调用方法时,方法调用被编码分派到调用处理程序的invoke
方法。
会自动触发invoke
方法
代码测试
根据p
神的测试案例,加点东西,方便自己理解在readObject
中的调用
Part 1
创建一个类,实现InvocationHandler
接口
主要功能就是,监听代理对象get
方法调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import java.lang.reflect.Method; import java.lang.reflect.InvocationHandler; import java.util.Map;
public class ExampleInvocationHandler implements InvocationHandler { protected Map map; public ExampleInvocationHandler(Map map) { this.map = map; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().compareTo("get") == 0) { System.out.println("Map Object " + this.map); System.out.println("Hook method: " + method.getName()); return "Hacked Object"; } return method.invoke(this.map, args); } }
|
Part 2
创建一个类,实现代理对象的创建,并设置Map
对象的键值对
并模拟(假设)触发readObject(test)
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import java.util.HashMap; import java.lang.reflect.InvocationHandler; import java.util.Map; import java.lang.reflect.Proxy;
public class App { public static void main(String[] args) throws Exception { InvocationHandler handler = new ExampleInvocationHandler(new HashMap()); Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] {Map.class}, handler); proxyMap.put("a", "world"); Object demo = new Demo(proxyMap); String result = (String) ((Demo) demo).test(); System.out.println(result); } }
|
Part 3
实现一个类,假设存在readObject(test)
方法
通过设置的成员属性调用get
方法,完成一次模拟的readObject
1 2 3 4 5 6 7 8 9 10 11 12 13
| import java.util.Map;
public class Demo { private Map a; public Demo(Map obj){ this.a = obj; } public Object test(){ String result = (String) this.a.get('a'); return result; } }
|
代码流程
- 运行
App
中的main
方法
- 创建
ExampleInvocationHandler
对象的实例
- 为
ExampleInvocationHandler
对象创建代理对象
- 设置
Map
对象的键值对
- 实例化一个
Demo
对象,并将成员属性a
设置为代理对象
- 调用
Demo
(自动触发Demo
)的test
(readObject
)方法
- 通过
this.a.get
自动触发代理对象的invoke
方法
测试结果
运行结果如下

可以发现,对象已经被代理,且Map
的键值对就是我们设置的键值对