动态代理核心源码实现
public Object getProxy() {
//jdk 动态代理的使用方式
return Proxy.newProxyInstance(
this.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this//InvocationHandler接口的自定义实现类
);
}
1
2
3
4
5
6
7
8
使用JDK动态代理,首先要自定义InvocationHandler接口的实现类,书写代理类的控制逻辑。

示例:

public class JDKDynamicProxyHandler implements InvocationHandler {

private Object target;

public JDKDynamicProxyHandler(Class clazz) {
try {
this.target = clazz.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

preAction();
Object result = method.invoke(target, args);
postAction();
return result;
}

public Object getProxy() {
return Proxy.newProxyInstance(
this.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}

private void preAction() {
System.out.println("JDKDynamicProxyHandler.preAction()");
}

private void postAction() {
System.out.println("JDKDynamicProxyHandler.postAction()");
}
}
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
具体在使用时,只需要通过以下来获取代理类

Object proxy = Proxy.newProxyInstance(
this.getClass().getClassLoader(),
target.getClass().getInterfaces(),
invocationHandler);
1
2
3
4
这段代码的核心逻辑在Proxy的newProxyInstance中。

基于JDK8的动态代理实现。

public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
//...
//克隆接口的字节码
final Class<?>[] intfs = interfaces.clone();
//...
//从缓存中获取或生成指定的代理类
Class<?> cl = getProxyClass0(loader, intfs);
try {
//获取构造函数
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
//根据Proxy的有参构造函数构造出代理类
return cons.newInstance(new Object[]{h});
}
//...
}

private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
//...接口的数量不能超过65535
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}

// WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache=new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
//如果指定的类加载器已经生成代理实现类,那么直接从缓存获取副本,否则生成新的代理实现类。
return proxyClassCache.get(loader, interfaces);
}

//proxyClassCache的get方法
public V get(K key, P parameter) {

//...key为classloader,parameter为接口的Class数组
//删除过时的entry
expungeStaleEntries();
//构造CacheKey key为null时,cacheKey为object对象,否则为虚引用对象
Object cacheKey = CacheKey.valueOf(key, refQueue);

//根据cacheKey加载二级缓存
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
//如果不存在,构造二级缓存
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
//如果出于并发情况,返回了缓存map,将原缓存map赋值给valuesMap
valuesMap = oldValuesMap;
}
}

//构造二级缓存key,subKey
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
//获取生成代理类的代理类工厂
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;

while (true) {
//循环获取生成代理类的代理类工厂
if (supplier != null) {
// 如果代理类工厂不为空,通过get方法获取代理类。该supplier为WeakCache的内部类Factory
V value = supplier.get();
if (value != null) {
return value;
}
}

if (factory == null) {
//代理工厂类为null,创建代理工厂类
factory = new Factory(key, parameter, subKey, valuesMap);
}

if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
supplier = factory;
}
// else retry with winning supplier
} else {
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
supplier = factory;
} else {
// retry with current supplier
supplier = valuesMap.get(subKey);
}
}
}
}

//Factory的get方法
public synchronized V get() { // serialize access
// re-check
Supplier<V> supplier = valuesMap.get(subKey);
if (supplier != this) {
//如果在并发等待的时候有变化,返回null,继续执行外层的循环。
return null;
}
//创建新的代理类
V value = null;
try {
//通过ProxyClassFactory的apply方法生成代理类
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // remove us on failure
valuesMap.remove(subKey, this);
}
}
//用CacheValue包装value值(代理类)
CacheValue<V> cacheValue = new CacheValue<>(value);

//将cacheValue放入reverseMap
reverseMap.put(cacheValue, Boolean.TRUE);
return value;
}

//ProxyClassFactory类的apply方法
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
//校验class是否正确,校验class是否是interface,校验class是否重复
//...
//代理类的包名
String proxyPkg = null; // package to define proxy class in
//代理类的访问修饰符
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
//记录非public修饰的被代理类接口,用来作为代理类的包名,同时校验所有非public修饰的被代理类接口必须处于同一包名下
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}

if (proxyPkg == null) {
// 如果没有非public的接口类,包名使用com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}

/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
//构造代理类名称,使用包名+代理类前缀+自增值作为代理类名称
String proxyName = proxyPkg + proxyClassNamePrefix + num;

//生成代理类的字节码文件
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
//通过native的方法生成代理类
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
}
//...
}
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
总结
Proxy.newProxyInstance方法获取代理类执行过程:
Proxy.getProxyClass0()方法获取代理类class。

WeakCache.get()方法
CacheKey.valueOf(key, refQueue)获取一级缓存key,cacheKey。
ConcurrentMap.get()方法获取二级缓存ConcurrentMap。
KeyFactory生成二级缓存key,subKey。
ConcurrentMap.get()方法获取二级缓存value,Supplier实现类Factory。
Factory不存在,则通过new Factory生成新的Factory。
通过Factory的get方法获取二级缓存值CacheValue实例。
通过Factory内部缓存ConcurrentMap.get()方法获取Supplier实例。
如果Supplier实例不存在,通过ProxyClassFactory.apply()方法生成代理类class。
使用cacheValue包装代理类class。
Class.getConstructor(InvocationHandler.class)获取有参(InvocationHandler)构造函数。

Constructor.newInstance(InvocationHandler)获取代理类。

代理类的包名:由被代理类实现的接口的限定修饰符确定,如果有非public修饰符,则包名为非public接口所在包路径。如果多个非public修饰符的接口,这些接口必须处于同一包中。如果全为public接口,那么包名为com.sun.proxy。

代理类的全路径类名:包名+代理类名前缀($Proxy)+自增数字。

Proxy内部采用了多级缓存缓存生成的代理类class,避免重复生成相同的代理类,从而提高性能。

缓存使用的类是WeakCache。

//初始化
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
1
2
3
一级缓存的key是CacheKey,CacheKey由classloader和refQueue(引用队列)构成。

一级缓存的value是ConcurrentMap<Object, Supplier> 。

二级缓存的key,subKey,由subKeyFactory(KeyFactory)工厂类根据被代理类实现的接口数量生成。

二级缓存的value是Supplier的实现类,Factory。

代理类class由二级缓存的get()方法获得,最终生成代理类class的是ProxyClassFactory的apply方法,apply方法生成字节码文件后,通过调用native方法defineClass0最终生成Class。

代理类class反编译后的代码
注意:要想看到反编译后的class文件,需加个系统变量,sun.misc.ProxyGenerator.saveGeneratedFile为true,也可在测试代码中手动指定System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”);

package com.sun.proxy;

import com.xt.design.pattern.proxy.dynamic.jdk.HelloService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements HelloService {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;

public $Proxy0(InvocationHandler var1) throws {
super(var1);
}

public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}

public final void sayHello() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}

public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}

public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}

static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("com.xt.design.pattern.proxy.dynamic.jdk.HelloService").getMethod("sayHello");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
从上述生成后的代理类class文件可以看出:

代理类继承了Proxy类,实现了要代理类的接口
代理类和Proxy都有有参构造函数,且参数为InvocationHandler对象。
代理类调用方法都是通过InvocationHandler去调用的。
方法返回对象都是包装类型,如果原先返回的是基本数据类型,如int,会转换成包装类返回。
JDK动态代理要求被代理类必须实现接口的原因是:生成的代理类要继承Proxy,Java是单继承、多实现的,所以只能通过实现接口的方式来生成代理类。

但是代理类为什么要继承Proxy???继承Proxy只是获得了一个有参构造,从而将InvocationHandler传入,具体的调用方法都是通过InvocationHandler来的,那为什么不直接引用InvocationHandler,从而避免单继承带来的被代理类必须实现接口的限制?

Stack Overflow上有人说这是标准。
---------------------

Java设计模式之JDK动态代理原理的更多相关文章

  1. 设计模式之jdk动态代理模式、责任链模式-java实现

    设计模式之JDK动态代理模式.责任链模式 需求场景 当我们的代码中的类随着业务量的增大而不断增大仿佛没有尽头时,我们可以考虑使用动态代理设计模式,代理类的代码量被固定下来,不会随着业务量的增大而增大. ...

  2. Java设计模式系列之动态代理模式(转载)

    代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Sub ...

  3. 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)

    代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...

  4. Java Proxy和CGLIB动态代理原理

    动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译时就确定了,而动态代理的代理关 ...

  5. Java中的JDK动态代理

    所谓代理,其实就是相当于一个中间人,当客户端需要服务端的服务时,不是客户直接去找服务,而是客户先去找代理,告诉代理需要什么服务,然后代理再去服务端找服务,最后将结果返回给客户. 在日常生活中,就拿买火 ...

  6. Java学习笔记--JDK动态代理

    1.JDK动态代理     JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和 ...

  7. 设计模式之Jdk动态代理

    什么是动态代理呢?就是在java的运行过程中,动态的生成的代理类.(为了更熟悉的了解动态代理,你必须先熟悉代理模式,可点击设计模式之代理模式 阅读)我们知道java属于解释型语言,是在运行过程中,寻找 ...

  8. java设计模式中的动态代理

    Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...

  9. 代理模式及jdk动态代理原理

    代理模式 :为其它对象提供代理,以控制对这个对象的访问. 代理模式的特征:代理类(proxyClass)与委托类(realClass)有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转 ...

随机推荐

  1. poj1330 lca 最近公共祖先问题学习笔记

    首先推荐两个博客网址: http://dongxicheng.org/structure/lca-rmq/ http://scturtle.is-programmer.com/posts/30055. ...

  2. 利用Calendar类测试电脑运行速度

    今天学习了很多新知识! 这里使用了Calender类来获取系统时间,并计算循环1w次的时间,判断电脑处理时间. import java.util.Calendar; public class Arra ...

  3. python 执行环境

    一些函数 执行其它非python程序 1 一些函数 callable callable()是一个布尔函数,确定一个对象是否可以通过函数操作符(())来调用.如果函数可调用便返回True,否则便是Fal ...

  4. JS 仿淘宝幻灯片 非完整版 小案例

    仿淘宝幻灯片,基础版,后期效果是要做到每次点击小圆点,切换都无缝 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" &quo ...

  5. Android studio第一次使用配置(三)gradle项目构建

    1.gradle的概念 2.gradle配置jar包.和libs目录导入jar包的差别 3.签名打包: (1)Studio (2)命令行 (3)gradle wrapper的原理 4.BuildCon ...

  6. Oracle VM VirtualBox使用的注意事项

    Oracle VM VirtualBox使用的注意事项 Oracle VM VirtualBox 上克隆虚拟机 方法一 1.复制源虚拟里的 vdi 文件到新的目录 2.命令行进入 Oracle VM  ...

  7. React-Router 中文简明教程(上)

    概述 说起 前端路由,如果你用过前端 MV* 框架构建 SPA 应用(单页面应用),对此一定不陌生. 传统开发中的 路由,是由服务端根据不同的用户请求地址 URL,返回不同内容的页面,而前端路由则将这 ...

  8. oc26--Property,省略setget的声明

    // // Person.h #import <Foundation/Foundation.h> @interface Person : NSObject { int _age; } /* ...

  9. Codesys——常用快捷键列表

    F1——打开Help文档: F2——打开Input Assistant: F5——执行程序(Start): F9——添加或取消断点(Toggle Breakpoint): F8——单步进入(Step ...

  10. DataGuard总体结构

    一.DataGuard总体结构 总体目标 1.   描述计划和非计划停机的不同因数 2.   DataGuard的主要组件 3.   物理以及逻辑DataGuard的异同 4.   建立DataGua ...