动态代理原理分析

前言

代理模式(Proxy design pattern)可以分为静态代理和动态代理,两种代理模式本质都是对外隔离真实的业务类,并且对外通过代理类,引入代理类的附加功能。对于动态代理的理解,其动态性并不是表现在省去了编写代理类的代码的工作量,而是表现在当真实的业务类、接口类还未知的时候,就可以确定了代理类的行为。

源码分析

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
// IFractory 接口
public interface IFractory {
void createProduct();
}


public class ToyFractory implements IFractory {
@Override
public void createProduct() {
System.out.println("生产玩具的厂家");
}
}


public class DynamicProxy implements InvocationHandler {

private IFractory mIFractory;

public IFractory getIFractory() {
return mIFractory;
}

public void setIFractory(IFractory pIFractory) {
mIFractory = pIFractory;
}

public Object createProxyInstance(){
return Proxy.newProxyInstance(mIFractory.getClass().getClassLoader(),
mIFractory.getClass().getInterfaces(),
this); // 注释 1
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object lInvoke = method.invoke(mIFractory, args);
return lInvoke;
}
}

public class TestDynamicProxy {

public static void main(String[] args) {

ToyFractory lToyFractory = new ToyFractory();
DynamicProxy lDynamicProxy = new DynamicProxy();
lDynamicProxy.setIFractory(lToyFractory);

IFractory lProxyInstance = (IFractory) lDynamicProxy.createProxyInstance();

lProxyInstance.createProduct();

}
}

上面代码简单创建了 DynamicProxy 类继承了 InvocationHandler 类,并重写 InvocationHandler#invoke() 方法,然后在 TestDynamicProxy 类中创建真正的业务类,并通过 lDynamicProxy#createProxyInstance()生成代理类对象,代理类对象通过调用 createProduct() 方法,间接地调用真正的业务类的真实业务,如上述代码。

我们需要分析动态代理是如何为我们创建代理(Proxy)类的,我们查看[注释 1 ]处的代码细节:

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
// Proxy.java#newProxyInstance()
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);

// 克隆出一份class<?>[] 数组,避免后续的操作干扰到 interfaces数组;(Java 语言是值传递)
final Class<?>[] intfs = interfaces.clone();

....

/*
* Look up or generate the designated proxy class.
*/
// 注释 2
// 根据参数生成指定的代理类对象
Class<?> cl = getProxyClass0(loader, intfs);

/*
* Invoke its constructor with the designated invocation handler.
*/
try {

...

final Constructor<?> cons = cl.getConstructor(constructorParams);

...

if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
// 通过反射调用,生成代理类对象并返回
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
...
} catch (InvocationTargetException e) {
...
} catch (NoSuchMethodException e) {
...
}
}

方法 newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 主要的作用是根据指定的接口返回对应的代理类对象。

在上面的 Proxy#newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 方法中,我去掉了一些不重要的代码逻辑,这个方法主要的作用是通过 Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) 生成一个代理类的 Class 类,然后通过反射运行时获取到该代理类的实例,具体代码如上。

在 [注释 2]处,通过查看 Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) 方法的具体实现,可以发现返回的 Class 代理类是通过给定的类加载器、指定的类接口而生成的,在程序运行期间会存储在内存中,在再次需要的时候,直接返回,具体代码如下:

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

...

/**
* a cache of proxy classes
*/
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

...

/**
* Generate a proxy class. Must call the checkProxyAccess method
* to perform permission checks before calling this.
*/
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
// 接口数量不可以超过 65535
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
// 注释 3
return proxyClassCache.get(loader, interfaces);
}

通过解读上面 Proxy#getProxyClass0(ClassLoader loader, Class<?>... interfaces) 的注释,可以知道:如果代理类的 Class 存在,则直接从内存中把 Class 返回,如果代理类不存在通过则通过 ProxyClassFactory 创建代理类。

那么,这时候我们心里面会有疑问,ProxyClassFactory 是如何创建代理类 Class 的呢?

带着疑问,我们继续沿着代码往下面读。通过查阅代码,我们发现 [注释 3] 处的 proxyClassCache 变量是 WeakCache<ClassLoader, Class<?>[], Class<?>> 类型的,并且通过 new WeakCache<>(new KeyFactory(), new ProxyClassFactory()) 初始化了该变量,并在初始化的同时,发现 ProxyClassFactory 这个创建代理类的重要参数,传入 WeakCache 构造方法的第二个参数,那么我们在往下阅读的时候,需要额外关注 WeakCache 的构造方法的第二个参数。通过阅读 WeakCache#get(K key, P parameter) 方法:

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
public V get(K key, P parameter) {

...

Object cacheKey = CacheKey.valueOf(key, refQueue);

// lazily install the 2nd level valuesMap for the particular cacheKey
// map 是 ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> 类型的
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
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;

while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
// 注释 4
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
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);
}
}
}
}

WeakCache#get(K key, P parameter) 的方法逻辑比较复杂,但比较重要的是在 [注释 4] 处,代码 supplier.get() 中, 可以通过代码知道,supplier 是通过 new Factory(key, parameter, subKey, valuesMap) 初始化的,因此我们可以阅读 Factory#get() 方法,代码如下:

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

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
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 {
// 注释 5
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // remove us on failure
valuesMap.remove(subKey, this);
}
}
// the only path to reach here is with non-null value
assert value != null;

// wrap value with CacheValue (WeakReference)
// 把创建出的代理类 Class 存储在 CacheValue
CacheValue<V> cacheValue = new CacheValue<>(value);

// put into reverseMap
// cacheValue 继续放进 reverseMap 里面;
reverseMap.put(cacheValue, Boolean.TRUE);

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

通过阅读代码,我们可以发现 FactoryWeakCache 的普通内部类。Factory 类的代码逻辑比较简单,我们主要看 [注释 5] 处,代码 valueFactory.apply(key, parameter) 返回的值,正是我们需要的代理类 Class 对象,那么 valueFactory 是什么呢?

通过再次阅读代码,我们可以发现,valueFactory 正是源码中 new WeakCache<>(new KeyFactory(), new ProxyClassFactory()) 的第二个参数 new ProxyClassFactory(), 那么我们可以尝试推断:

1
2
3
Class<?> proxy = proxyClassCache.get(loader, interfaces);
// 等价于
Class<?> proxy = new ProxyClassFactory().apply(loader, interfaces);

当然,上面的等价只是抽离了很多相关的代码而推断出的结论,实际上并不可以编译的。那么我们现在只需要专注于 ProxyClassFactory#apply(ClassLoader loader, Class<?>[] interfaces) 方法,通过下面阅读源码:

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
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] 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对象
Class<?> interfaceClass = null;
try {

interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}

....
}

// 代理类的包路径
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
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}

/*
* Choose a name for the proxy class to generate.
*/
// 数字类加操作,从数字 0 开始(原子操作)
long num = nextUniqueNumber.getAndIncrement();
// 拼接代理类的名字,如 $Proxy0 ...
String proxyName = proxyPkg + proxyClassNamePrefix + num;

/*
* Generate the specified proxy class.
*/
// 生成指定的代理类,这里是一个 byte 类型的数组
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
// 注释 6
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());
}
}

当我们继续阅读 private static native Class<?> defineClass0(ClassLoader loader, String name, byte[] b, int off, int len) 方法的时候,发现其是一个本地方法,底层如何实现我们在这里就不深究了(主要是我懒)。

ProxyClassFactory#apply(ClassLoader loader, Class<?>[] interfaces) 方法中,主要是准备创建 Proxy 代理类的准备工作,并没有太多复杂难懂的代码。

那么 proxyClassFile 内容是怎样的呢?我们可以通过输入输出流,把 proxyClassFile 输出到 .class 类型的文件中,文件代码如下:

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

import cn.xxx.proxy_2.IFractory;
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 IFractory {
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);
}
}

// 注释 7
public final void createProduct() throws {
try {
super.h.invoke(this, m3, (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"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("cn.enjoyedu.proxy_2.IFractory").getMethod("createProduct");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}

通过阅读生成的 $proxy0.class 源码,我们可以主要阅读 [注释 7] 处,super.h.invoke(this, m3, new Object[]{var1}) 中,h表示的是 Proxy#InvocationHandler, 那么我们就可以得出:

1
2
3
4
InvocationHandler#invoke(
new Proxy(),
Class.forName("cn.xxx.proxy_2.IFractory").getMethod("saleManTools", Class.forName("java.lang.String")),
new Object[]{var1})

以上,是动态代理源码分析的主要内容,知道动态代理主要是通过代码在内存中,生成指定类加载器和类接口的代理对象,然后保存在内存中,在需要的时候返回指定的代理实例。

通过上述的代码分析,我们也可以知道,动态代理会占用一定的内存,而且效率相对于静态代理较低,但这样子避免了在未确定真实类、以及对应的接口的时候,就可以确定代理类的行为,从而可以分离代理类和真实业务类的耦合,可以很灵活地应用在不同的场景中。

本文标题:动态代理原理分析

文章作者:

发布时间:2020年03月19日 - 10:03

最后更新:2021年06月20日 - 19:06

原始链接:https://hndroid.github.io/2020/03/19/%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。