目标
通过代码示例了解动态代理语法
示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Demo {
interface MyMath1 {
public Integer sum(Integer a, Integer b);
}
static class MyMathImpl implements MyMath1 {
@Override
public Integer sum(Integer a, Integer b) {
return a + b;
}
}
public static void main(String[] args) {
MyMath1 tg = new MyMathImpl();
// 创建对象代理
MyMath1 math = (MyMath1) Proxy.newProxyInstance(tg.getClass().getClassLoader(), tg.getClass().getInterfaces(), new InvocationHandler() {
MyMath1 target = tg;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long startTime = System.nanoTime();
// 代理对象执行方法
Object result = method.invoke(tg, args);
long estimatedTime = System.nanoTime() - startTime;
System.out.println("方法耗时-" + estimatedTime);
// 问: 形参proxy是干嘛的?
// 注: 此时有两个MyMath1对象(tg, math),以及一个this关键字
// this == InvocationHandler对象, proxy == math对象
return result;
}
});
// 调用被代理后的方法
System.out.println(math.sum(1, 2));
}
}
|
动态代理分jdk版,和cglib版
此示例代码为 jdk版
代码通过为tg对象创建代理,实现了统计方法执行时间的功能
jdk版-动态代理 利用反射机制生成一个实现代理接口的匿名类。
math对象本就继承了Proxy,java不能多重继承,只能用接口,因此tg对象必须实现过接口。
cglib版-动态代理 要求tg必须实现接口,但要求tg不能为final-class
动态代理-场景
有动态代理的地方肯定有反射,因为其建立在反射之上
- orm框架的接口注入
- aop(注解@Transaction, @Cacheable)
- 远程调用 (反射+ 动态代理+ 序列化== 调用dubbo的rpc服务调用)
文章作者
duansheli
上次更新
2019-12-25
(325c7b3)