java动态代理:JDK动态代理的内部原理
Posted pgrDog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java动态代理:JDK动态代理的内部原理相关的知识,希望对你有一定的参考价值。
上一章我们简单的讲解了什么是动态代理和如何使用动态代理。
这章讲解一下jdk的动态代理的内部实现:
从代码可以看出是调用了Proxy.newProxyInstance,进入该方法,查看源代码:
主要的有map和reverseMap,其中map的key是ClassLoader类型,Value是concurrentMap类型,而concurrentMap里的key是由subKeyFactory组合ClassLoader和接口类数组组合而成,value有两种可能,一种是Factory对象,一种是CacheValue,Factory对象是生产我们需要的ProxyClass的,而CacheValue是存储已经生产过的ProxyClass。
首先查看测试代码:
//创建一个静态方法,生成代理类,
public static Object newProxyInstance(Object speak){
System.out.println(JDKDynamicProxy.class.getClassLoader().toString());
return Proxy.newProxyInstance(JDKDynamicProxy.class.getClassLoader(),new Class[]{Speak.class,Eat.class}, new JDKDynamicProxy(speak));
}
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}
final Class<?>[] intfs = interfaces.clone();//拷贝一份接口类数组,我们的例子是传入{Speak.class,Eat.class}
final SecurityManager sm = System.getSecurityManager();//获取安全管理器组件
if (sm != null) {//判断是否有权限去访问
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
//根据classloader和接口类数组动态创建Proxy.cass
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
//Proxy.class存在一个以InvocationHandler.class为类型的参数,获取该构造器
//看起来是我们常用的代理模式
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {//判断是Proxy.class是否包含不是public类型的接口
// create proxy instance with doPrivilege as the proxy class may
// implement non-public interfaces that requires a special permission
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
return newInstance(cons, ih);
}
});
} else {
//返回Proxy.class实例
return newInstance(cons, ih);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
}
}
从代码可以看出,核心方法是:
Class<?> cl = getProxyClass0(loader, intfs);
这个方法根据我们传入的接口类和类加载器(若没有自定义加载器,默认是AppClassLoader),此方法是动态生成实现了我们传入的接口的Proxy.class,还有一个Proxy(InvocationHandler h)构造器,传入我们之前实现了InvocationHandler 接口的实现类JDKDynamicProxy.class,之后的newInstance就是反射创建实例并返回。 先不管那些权限判断的代码,主要看getProxyClass0方法:
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {//接口数量不能超过65535,刚好是一个int类型的最大值
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
return proxyClassCache.get(loader, interfaces);
}
我们看一下proxyClassCache的定义:
/**
* a cache of proxy classes
*/
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
proxyClassCache是静态变量,从注解可以看出是缓存动态生成的ProxyClass,以便下次再调用的时候可以跳过动态生成java字节码这一步,我们再看一下WeakCache类(题外话:我本地的jdk是1.7版本,在jdk的rt.jar包里是没有 java.lang.reflect.WeakCache这个类的,但运行又没有报错,于是看了一下虚拟机的运行环境里的rt.jar,发现是存在这个类的,而且BiFunction伪函数指针是java8才有的):
WeakCache主要的内部类有:CacheKey,CacheValue,Factory,Supplier,Value。
其中CacheValue实现Supplier的接口中get方法由WeakReference的get方法来实现。
查看WeakCache的成员:
private final ReferenceQueue<K> refQueue = new ReferenceQueue();//弱引用队列
//(ClassLoader key ,(<CLassloader,Class<?>[]> key ,Factory value) value)
private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap();
private final ConcurrentMap<Supplier<V>, Boolean> reverseMap = new ConcurrentHashMap();
private final BiFunction<K, P, ?> subKeyFactory;//Key的创建工厂
private final BiFunction<K, P, V> valueFactory;//value的创建工厂
看主要方法:
//调用这个方法获取动态生成的class
public V get(K paramK, P paramP)
{
Objects.requireNonNull(paramP);//检测传入的接口数组是否为空
expungeStaleEntries();//删除因为只有弱引用没有强引用指向的被gc回收后遗留下来的WeakReference对象,
Object localObject1 = CacheKey.valueOf(paramK, this.refQueue); //创建一个CacheKey,paramK是ClassLoader对象,CacheKey是继承WeakReference类,
Object localObject2 = (ConcurrentMap)this.map.get(localObject1);//判断map中是否存在相同的key
if (localObject2 == null)//不存在
{
localObject3 = (ConcurrentMap)this.map.putIfAbsent(localObject1, localObject2 = new ConcurrentHashMap());//不存在则存入<ClassLoader:localObject1,ConcurrentHashMap:localObject2>,若存在则map.get(localObject1)得到localObject3
if (localObject3 != null)
localObject2 = localObject3;
}
Object localObject3 = Objects.requireNonNull(this.subKeyFactory.apply(paramK, paramP));//创建二元键<classloader,Class<?>[]>
Object localObject4 = (Supplier)((ConcurrentMap)localObject2).get(localObject3);//从localObject2根据我们给的<classloader,Class<?>[]>获取Value,有可能是Factory对象,也有可能是CacheValue对象,Factory则调用动态创建ProxyClass,创建完ProxyClass后封装成CacheValue,然后用CacheValue替换掉Factory。
Factory localFactory = null;
while (true)
{
if (localObject4 != null)
{
//核心代码
Object localObject5 = ((Supplier)localObject4).get();//调用的有可能是Factory的get方法,也有可能是CacheValue的get方法
if (localObject5 != null)
return localObject5;
}
if (localFactory == null)//为该键值<classloader,intfaces>创建一个工厂
localFactory = new Factory(paramK, paramP, localObject3, (ConcurrentMap)localObject2);
if (localObject4 == null)//把创建的工厂放入localObject2中
{
localObject4 = (Supplier)((ConcurrentMap)localObject2).putIfAbsent(localObject3, localFactory);
if (localObject4 != null)
continue;
localObject4 = localFactory;
continue;
}
//当localObject4存在,但Facotry的get方法并返回null时,就替换掉replace(K key, V oldValue, V newValue)
if (((ConcurrentMap)localObject2).replace(localObject3, localObject4, localFactory))
{
localObject4 = localFactory;
continue;
}
localObject4 = (Supplier)((ConcurrentMap)localObject2).get(localObject3);
}
}
CacheValue的get方法是返回已生成的Class文件,故不再关注,重点关注Factory的get方法
public synchronized V get()
{
//factory获取
WeakCache.Supplier localSupplier = (WeakCache.Supplier)this.valuesMap.get(this.subKey);
if (localSupplier != this)
return null;
Object localObject1 = null;
try
{
//调用ProxyClassFactory的apply,返回Class类型为localObject1
localObject1 = Objects.requireNonNull(WeakCache.this.valueFactory.apply(this.key, this.parameter));
}
finally
{
if (localObject1 == null)
this.valuesMap.remove(this.subKey, this);
}
assert (localObject1 != null);
WeakCache.CacheValue localCacheValue = new WeakCache.CacheValue(localObject1);
//因为Factory和CacheValue都继承Supplier,故可以将原本指向Factory对象替换成指向CacheValue
if (this.valuesMap.replace(this.subKey, this, localCacheValue))
//缓存Class
WeakCache.this.reverseMap.put(localCacheValue, Boolean.TRUE);
else
throw new AssertionError("Should not reach here");
return localObject1;
}
其中WeakCache.this.valueFactory.apply(this.key, this.parameter) 是调用之前
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
/**
* 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
//生成类序列号和$Proxy组合成类名
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@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<?> 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: " +以上是关于java动态代理:JDK动态代理的内部原理的主要内容,如果未能解决你的问题,请参考以下文章