Jiang's blog

动态代理源码解析(基于jdk8)

Word count: 4.8kReading time: 23 min
2020/08/01 Share

什么是动态代理?

动态代理是一种方便运行时动态构建代理、动态处理代理方法调用的机制,很多场景都是利用类似机制做到的,比如用来包装 RPC 调用、面向切面的编程(AOP)。

动态代理的实现方式

动态代理实现的方式有很多,我这里主要了解了两种最常见的方式

  • JDK 自身提供的动态代理,就是主要利用了反射机制。
  • 利用更高性能的字节码操作机制,类似 ASM、cglib(基于 ASM)、Javassist 等。

由静态代理到动态代理

代理就是可以认为在不修改已有代码的前提下,在目标对象基础上增加额外的功能。

首先定义一个UserService接口,表示被代理的接口

1
2
3
4
5
package com.jiang.jdk.proxy;

public interface UserService {
void play(String name);
}

然后实现这个接口

1
2
3
4
5
6
7
8
9
10
11
12
package com.jiang.jdk.proxy.impl;

import com.jiang.jdk.proxy.UserService;

public class UserServiceImpl implements UserService {


@Override
public void play(String name) {
System.out.println(name + "正在玩....");
}
}

1.静态代理

首先构建一个UserServiceProxy接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.jiang.jdk.proxy.impl;

import com.jiang.jdk.proxy.UserService;

public class UserServiceProxy implements UserService {
// 被代理的服务
private UserService userService;

// 通过构造方法传入代理对象
public UserServiceProxy(UserService userService) {
this.userService = userService;
}

@Override
public void play(String name) {
System.out.println(name + "被代理前");
userService.play(name);
System.out.println(name + "被代理后");
}
}

使用静态代理, StaticProxyTest.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.jiang.jdk.proxy;

import com.jiang.jdk.proxy.impl.UserServiceImpl;
import com.jiang.jdk.proxy.impl.UserServiceProxy;

public class StaticProxyTest {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserServiceProxy userServiceProxy = new UserServiceProxy(userService);
userServiceProxy.play("娇梅");
}
}

结果如下:
娇梅被代理前
娇梅正在玩….
娇梅被代理后

可以看到,静态代理模式在不改变目标对象的前提下,实现了对目标对象的功能扩展,但是静态方法也有非常明显的缺点,静态代理实现了目标对象的所有方法,一旦目标接口增加方法,代理对象和目标对象都要进行相应的修改,增加维护成本。而且静态代理的重用性不强。

2.动态代理

定义InvocationHandlerImpl实现InvocationHandler接口,重写invoke方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.jiang.jdk.proxy.impl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class InvocationHandlerImpl implements InvocationHandler {
// 声明被代理的对象
private Object proxyedObj;

public InvocationHandlerImpl(Object proxyObj) {
this.proxyedObj = proxyObj;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("被代理前");
Object invoke = method.invoke(proxyedObj, args);
System.out.println("被代理后");
return invoke;
}
}

使用动态代理,DynamicProxyTest.java中不难看出,代理对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.jiang.jdk.proxy;

import com.jiang.jdk.proxy.impl.InvocationHandlerImpl;
import com.jiang.jdk.proxy.impl.UserServiceImpl;

import java.lang.reflect.Proxy;

public class DynamicProxyTest {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
InvocationHandlerImpl handler = new InvocationHandlerImpl(userService);
//第一个参数是指定代理类的类加载器(我们传入当前测试类的类加载器)
//第二个参数是代理类需要实现的接口(我们传入被代理类实现的接口,这样生成的代理类和被代理类就实现了相同的接口)
//第三个参数是invocation handler,用来处理方法的调用。这里传入我们自己实现的handler
UserService proxyObject = (UserService) Proxy.newProxyInstance(DynamicProxyTest.class.getClassLoader(),
userService.getClass().getInterfaces(), handler);
proxyObject.play("娇梅");
}
}

结果如下:
娇梅被代理前
娇梅正在玩….
娇梅被代理后

源码解析

1. 从newProxyInstance入口开始解析

从DynamicProxyTest.java中不难看出,代理对象proxyObject是从Proxy的newProxyInstance中获得的,所以newProxyInstance就是整个源码解析的入口。

newProxyInstance ——> java\lang\reflect\Proxy.java

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
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
// h 指的是我们自定制的InvocationHandler的实例方法
// 这里的判空表示h是必须存在的
Objects.requireNonNull(h);

// 克隆我们被代理的类实现的所有接口
final Class<?>[] intfs = interfaces.clone();
// 系统的安全管理, 获取当前系统安全接口
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
//进行包访问权限、类加载器权限等检查

// Reflection.getCallerClass返回调用该方法的方法的调用类
// loader是指我们需要代理的类的类加载器
// intfs是上面克隆的接口
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}

/*
* Look up or generate the designated proxy class.
* 查找或生成指定的代理类,这里要重点分析,这个类到底是如何查找的
*/
Class<?> cl = getProxyClass0(loader, intfs);

/*
* Invoke its constructor with the designated invocation handler.
* 用指定的调用处理程序调用它的构造函数
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
// getConstructor字面意思就是获取代理类的构造器,传入的参数就是constructorParams ={ InvocationHandler.class }
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
// 通过构造器对象来实例化代理对象并返回
// 时刻记住, h 指的是我们自定制的InvocationHandler的实例方法,且不能为空
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}

newProxyInstance的主要作用可以归总为:

  1. Class<?> cl = getProxyClass0(loader, intfs),查找或生成指定的代理类;
  2. final Constructor<?> cons = cl.getConstructor(constructorParams), 获取代理类的构造器;
  3. 通过构造器对象来实例化代理对象并返回。

所以, getProxyClass0这个方法非常重要,因为它是代理类的来源之处

getProxyClass0 —–> java\lang\reflect\Proxy.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Generate a proxy class. Must call the checkProxyAccess method
* to perform permission checks before calling this.
* 生成一个代理类。必须调用checkProxyAccess方法,在调用之前执行权限检查。
*/
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}

// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
//如果代理类由给定加载器定义实现
//给定的接口存在,这将返回缓存的副本;
//否则,它将通过ProxyClassFactory创建代理类

// proxyClassCache为WeakCache<ClassLoader, Class<?>[], Class<?>>的对象
return proxyClassCache.get(loader, interfaces);
}

getProxyClass0主要是说这个代理类如果在缓存中存在,直接返回缓存的数据,否则的话就通过ProxyClassFactory创建代理类。
所以proxyClassCache.get(loader, interfaces)就是这个代理类的出处,继续往下看,先看一下proxyClassCache是什么,在看一下它的get方法。

1
2
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

alXu9A.png

WeakCache翻译过来是什么意思,虚弱的缓存。再看看ReferenceQueue,是不是很熟悉?如果了解过java引用就会发现,这不就是个弱引用加引用队列实现缓存的场景吗。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

在来看看proxyClassCache.get,实际上就是WeakCache.get。

WeakCache.get — >java\lang\reflect\WeakCache.java

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
public V get(K key, P parameter) {
// 从proxyClassCache的传参可以得出
// key是类加载器, parameter:接口数组
Objects.requireNonNull(parameter);

//清除已经被GC回收的弱引用
expungeStaleEntries();

// CacheKey是一个弱引用类, private static final class CacheKey<K> extends WeakReference<K>
Object cacheKey = CacheKey.valueOf(key, refQueue);

// lazily install the 2nd level valuesMap for the particular cacheKey
// map一级缓存,获取valuesMap二级缓存
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) {
valuesMap = oldValuesMap;
}
}

// create subKey and retrieve the possible Supplier<V> stored by that
// subKey from valuesMap

// subKeyFactory类型是KeyFactory,apply返回表示接口的key
// 此处的subKey也是弱引用的,下面会说明
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
// Factory 实现了supplier,我们实际是获取缓存中的Factory,调用其get方法,这里一会说明
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;

// 利用 CAS + 重试机制
while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
// 此supplier可能是缓存中取出来的,也可能是Factory新new出来的
V value = supplier.get();
if (value != null) {
return value;
}
}
// else no supplier in cache
// or a supplier that returned null (could be a cleared CacheValue
// or a Factory that wasn't successful in installing the CacheValue)

// lazily construct a Factory
// 懒加载建造工厂,初次循环一定为null,目的是上一步获取不到值工厂创建
if (factory == 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);
}
}
}
}

这里可以说是源码比较难理解的一点,我也不知道自己的理解是否完全正确,以后会慢慢修改。
首先get做了这样几件事:

  1. 通过CacheKey.valueOf(key, refQueue)获取cacheKey;
  2. 通过cacheKey从一级缓存map中获取二级缓存valuesMap;
  3. 通过subKeyFactory.apply(key, parameter)获取subKey,这一点很重要,而且有点绕,稍后分析;
  4. 通过subKey从二级缓存valuesMap中拿到supplier,这里的supplier就是工厂类Factory;
  5. 拿到工厂类就好做事了

首先分析subKeyFactory.apply(key, parameter)这个方法,由BiFunction<K, P, ?> subKeyFactory可知,subKeyFactory其实是BiFunction的实例,进入BiFunction中:

alxt4e.png

可以发现,有一个实现类KeyFactory,其实subKeyFactory就是KeyFactory的实例。

KeyFactory — > java\lang\reflect\Proxy.java

1
2
3
4
5
6
7
8
9
10
11
12
13
private static final class KeyFactory
implements BiFunction<ClassLoader, Class<?>[], Object>
{
@Override
public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
switch (interfaces.length) {
case 1: return new Key1(interfaces[0]); // the most frequent
case 2: return new Key2(interfaces[0], interfaces[1]);
case 0: return key0;
default: return new KeyX(interfaces);
}
}
}

key1 — > java\lang\reflect\Proxy.java

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
/*
* a key used for proxy class with 1 implemented interface
*/
private static final class Key1 extends WeakReference<Class<?>> {
private final int hash;

Key1(Class<?> intf) {
super(intf);
this.hash = intf.hashCode();
}

@Override
public int hashCode() {
return hash;
}

@Override
public boolean equals(Object obj) {
Class<?> intf;
return this == obj ||
obj != null &&
obj.getClass() == Key1.class &&
(intf = get()) != null &&
intf == ((Key1) obj).get();
}
}

可以发现,Key1实现了WeakReference<Class<?>>,也就是所谓的弱引用。
也就是说,subKeyFactory.apply(key, parameter)得到的subKey就是一个hash和代理的实现类class[]弱引用的引用对象。

接下来看一下supplier,V value = supplier.get();这里可以看出,supplier有get方法,并且是获取的值就是我们需要的代理类,首先看一下Supplier类

Supplier

a19C5T.png

可以看到, Factory 是 Supplier的实现类

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
private final class Factory implements Supplier<V> {

private final K key;
private final P parameter;
private final Object subKey;
private final ConcurrentMap<Object, Supplier<V>> valuesMap;

Factory(K key, P parameter, Object subKey,
ConcurrentMap<Object, Supplier<V>> valuesMap) {
this.key = key;
this.parameter = parameter;
this.subKey = subKey;
this.valuesMap = valuesMap;
}

@Override
// synchronized对获取代理类进行了同步限制
public synchronized V get() { // serialize access
// re-check
Supplier<V> supplier = valuesMap.get(subKey);
if (supplier != this) {
// something changed while we were waiting:
// might be that we were replaced by a CacheValue
// or were removed because of failure ->
// return null to signal WeakCache.get() to retry
// the loop
return null;
}
// else still us (supplier == this)

// create new value
V value = null;
try {
// 生成代理类
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // remove us on failure
//移除值,便于GC,清理弱引用
valuesMap.remove(subKey, this);
}
}
// the only path to reach here is with non-null value
assert value != null;

// wrap value with CacheValue (WeakReference)
// 用CacheValue (弱引用)包装值
CacheValue<V> cacheValue = new CacheValue<>(value);

// try replacing us with CacheValue (this should always succeed)
// 更新factory为cacheValue
if (valuesMap.replace(subKey, this, cacheValue)) {
// put also in reverseMap
reverseMap.put(cacheValue, Boolean.TRUE);
} else {
throw new AssertionError("Should not reach here");
}

// successfully replaced us with new CacheValue -> return the value
// wrapped by it
return value;
}
}

Factory的get方法 —> 也可以说是supplier.get, 主要干了以下几件事:

  1. 调用valueFactory.apply(key, parameter)生成了代理类;
  2. 生成代理类的缓存,并用弱引用包装起来
  3. 更新替换factory为cacheValue
  4. 返回代理类

valueFactory是什么呢, 它和subKeyFactory一样,是BiFunction的实例,BiFunction接口还有一个实现类,便是ProxyClassFactory,所以valueFactory也是ProxyClassFactory的实现类, valueFactory.apply会调用ProxyClassFactory的apply方法。

ProxyClassFactory

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
/**
* A factory function that generates, defines and returns the proxy class given
* the ClassLoader and array of interfaces.
*/
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";

// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();

@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

// loader:类加载器, interfaces:接口数组
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
* 验证类加载器是否解析此名称
* 类加载器和接口名解析出的是同一个类
*/
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
* 确保是一个接口
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
* 确保接口没重复
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}

String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
* 记录非公共代理接口的包,以便代理类将定义在相同的包中。验证所有非公开的代理接口在同一个包中。
*/
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) {
// if no non-public proxy interfaces, use com.sun.proxy package
// 如果没有非公共代理接口,则使用 com.sun.proxy 代理包
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}

/*
* Choose a name for the proxy class to generate.
* 选择要生成的代理类的名称。
* private static final AtomicLong nextUniqueNumber = new AtomicLong();
* 原子类,确保多线程安全,防止类名重复,类似于:$Proxy0,$Proxy1......
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num; // $Proxy0,$Proxy1......

/*
* Generate the specified proxy class.
* 生成指定的代理类。
*/

// 这是生成类字节码的方法:重点
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
//字节码loader进内存,加载代理类对象。defineClass0是一个native方法
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}
}

ProxyClassFactory主要做的事情有如下:

  1. 验证类加载器和接口解析是同一个类
  2. 验证所有非公开的代理接口在同一个包中。
  3. 生成指定的代理类。ProxyGenerator.generateProxyClass是生成类字节码的方法。

** ProxyGenerator.generateProxyClass**

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
public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
// 真正生成字节码的方法
final byte[] var4 = var3.generateClassFile();
// saveGeneratedFiles在最开始的定义中,默认为false,如下:
// private static final boolean saveGeneratedFiles = (Boolean)AccessController.doPrivileged(new GetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles"));
// 如果saveGeneratedFiles为true 则生成字节码文件;默认是不写文件的,动态classloader加载
// 当然,也可以通过返回的bytes自己输出(看别人的博客理解的)
if (saveGeneratedFiles) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
try {
int var1 = var0.lastIndexOf(46);
Path var2;
if (var1 > 0) {
Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
Files.createDirectories(var3);
var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
} else {
var2 = Paths.get(var0 + ".class");
}

Files.write(var2, var4, new OpenOption[0]);
return null;
} catch (IOException var4x) {
throw new InternalError("I/O exception saving generated file: " + var4x);
}
}
});
}

return var4;
}

从ProxyGenerator.generateProxyClass可以看出,如果jvm的参数sun.misc.ProxyGenerator.saveGeneratedFiles为true,且代理接口为public,我们就可以在com.sun.proxy文件中拿到类似$Proxy0.class的文件。

关于generateClassFile()方法我还不是很了解,这里先放出来,以后慢慢补充。

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
private byte[] generateClassFile() {
// 增加 hashcode、equals、toString方法
this.addProxyMethod(hashCodeMethod, Object.class);
this.addProxyMethod(equalsMethod, Object.class);
this.addProxyMethod(toStringMethod, Object.class);
Class[] var1 = this.interfaces;
int var2 = var1.length;

int var3;
Class var4;
for(var3 = 0; var3 < var2; ++var3) {
var4 = var1[var3];
Method[] var5 = var4.getMethods();
int var6 = var5.length;

for(int var7 = 0; var7 < var6; ++var7) {
Method var8 = var5[var7];
// 增加接口方法
this.addProxyMethod(var8, var4);
}
}

Iterator var11 = this.proxyMethods.values().iterator();

List var12;
while(var11.hasNext()) {
var12 = (List)var11.next();
checkReturnTypes(var12);
}

Iterator var15;
try {
this.methods.add(this.generateConstructor());
var11 = this.proxyMethods.values().iterator();

while(var11.hasNext()) {
var12 = (List)var11.next();
var15 = var12.iterator();

while(var15.hasNext()) {
ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next();
this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10));
this.methods.add(var16.generateMethod());
}
}

this.methods.add(this.generateStaticInitializer());
} catch (IOException var10) {
throw new InternalError("unexpected I/O Exception", var10);
}

if (this.methods.size() > 65535) {
throw new IllegalArgumentException("method limit exceeded");
} else if (this.fields.size() > 65535) {
throw new IllegalArgumentException("field limit exceeded");
} else {
this.cp.getClass(dotToSlash(this.className));
this.cp.getClass("java/lang/reflect/Proxy");
var1 = this.interfaces;
var2 = var1.length;

for(var3 = 0; var3 < var2; ++var3) {
var4 = var1[var3];
this.cp.getClass(dotToSlash(var4.getName()));
}

this.cp.setReadOnly();
ByteArrayOutputStream var13 = new ByteArrayOutputStream();
DataOutputStream var14 = new DataOutputStream(var13);

try {
var14.writeInt(-889275714);
var14.writeShort(0);
var14.writeShort(49);
this.cp.write(var14);
var14.writeShort(this.accessFlags);
var14.writeShort(this.cp.getClass(dotToSlash(this.className)));
var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));
var14.writeShort(this.interfaces.length);
Class[] var17 = this.interfaces;
int var18 = var17.length;

for(int var19 = 0; var19 < var18; ++var19) {
Class var22 = var17[var19];
var14.writeShort(this.cp.getClass(dotToSlash(var22.getName())));
}

var14.writeShort(this.fields.size());
var15 = this.fields.iterator();

while(var15.hasNext()) {
ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next();
var20.write(var14);
}

var14.writeShort(this.methods.size());
var15 = this.methods.iterator();

while(var15.hasNext()) {
ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next();
var21.write(var14);
}

var14.writeShort(0);
return var13.toByteArray();
} catch (IOException var9) {
throw new InternalError("unexpected I/O Exception", var9);
}
}
}

查看$Proxy0.class

idea -> Run-> Edit Configurations

a82tBR.png

a82x8U.png

$Proxy0.class文件打开如下,也可以用javap反编译查看更详细的信息

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
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.sun.proxy;

import com.jiang.jdk.proxy.UserService;
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 UserService {
private static Method m1;
private static Method m2;
private static Method m3;
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 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 void play(String var1) throws {
try {
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}

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"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.jiang.jdk.proxy.UserService").getMethod("play", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}

总结

动态代理是java典型的代理模式的应用,利用了弱引用加引用队列实现了缓存等应用,但是还是需要学习,里面很多知识没看明白。

CATALOG
  1. 1. 什么是动态代理?
  2. 2. 动态代理的实现方式
  3. 3. 由静态代理到动态代理
    1. 3.1. 1.静态代理
    2. 3.2. 2.动态代理
  4. 4. 源码解析
    1. 4.1. 1. 从newProxyInstance入口开始解析
  5. 5. 总结