动态代理(JDK或接口代理)
参考: https://www.bilibili.com/video/BV1V4411W7xy?p=4
IHello iHello = (IHello) Proxy.newProxyInstance(hello.getClass().getClassLoader(),
hello.getClass().getInterfaces(),
handler);
newProxyInstance:
- 在JVM里生成字节码,字节码加载后生成Class对象
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
getProxyClass0:
private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) {
// 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
return proxyClassCache.get(loader, interfaces);
}
proxyClassCache.get:
先从缓存ConcurrentMap<>中查找是否存在
Objects.requireNonNull(parameter);
expungeStaleEntries();
Object cacheKey = CacheKey.valueOf(key, refQueue);
// lazily install the 2nd level valuesMap for the particular 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) {
valuesMap = oldValuesMap;
}
}
创建:
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
其中subKeyFactory是BiFunction(Interface),具体实现类是:
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
其中实现的apply方法,其中阐述了$Proxy的由来。
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces)
private static final String proxyClassNamePrefix = "$Proxy";
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
在内存中直接生成了java字节码(.class),该类方法的源码从jdk1.6后就不开源:
/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
随后通过字节码拿到对象,这个方法也是一个native本地方法:
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
深入proxyClassFile:
利用反编译工具进入,$Proxy0进入硬盘
public final class $Proxy0 extends Proxy implements AaFactory{
// h指invocationHandler
h.invoke
// 最终调用了实现类中invoke方法
}
/**
拿到对象constructor后创建handler相关联的代理实例
*/
final Constructor<?> cons = cl.getConstructor(constructorParams);
return cons.newInstance(new Object[]{h});