IObject proxy = (IObject) Proxy.newProxyInstance(IObject.class.getClassLoader(),                                   
                             new Class[]{IObject.class},
                  new DynamicProxyHandler(real) );

使用Proxy类的静态方法newProxyInstance创建一个动态代理类

查看API文档:

public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
loader - 定义代理类的类加载器
interfaces - 代理类要实现的接口列表
h - 指派方法调用的调用处理程序

1、JDK动态代理要求,被代理的必须是个接口,单纯的类则不行,即interfaces必须是接口

2、JDK代理所生成的代理类都会继承Proxy类,同时代理类会实现所有传入的接口列表(即interfaces),因此可以强制类型转换成接口类型。

3、如果非要代理一个没有实现接口的类,同时该类的方法与其他接口的方法相同,则需要利用反射实现

//利用反射获取你想代理的类的方法
Method myMethod = targetClass.getClass().getDeclaredMethod(method.getName(), method.getParameterTypes());
myMethod.setAccessible(true);

4、newProxyInstance方法相当于getProxyClass方法

Proxy.getProxyClass(loader, interfaces).
getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });

源码分析:

@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
} //拷贝一份所有接口的数组
final Class<?>[] intfs = interfaces.clone();
/**
* 安全管理器主要用来防止恶意攻击,根据java安全策略文件觉得将哪组权限授予类
* 每个java应用都有自己的安全管理器,
* 如果要使用,可以在jvm启动时设定-Djava.security.manager选项,还可以同时指定安全策略文件。
* 如果在应用中启用了Java安全管理器,却没有指定安全策略文件,那么Java安全管理器将使用默认的安全策略,它们是由位于目录$JAVA_HOME/jre /lib/security中的java.policy定义的。
*/
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/**
* 调用getProxyClass0方法拿到代理类的Class对象
*/
Class<?> cl = getProxyClass0(loader, intfs);

调用getProxyClass0:

 /** 代理类的缓存 */
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory()); private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
//如果目标类的接口数大于65535
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
} // 如果代理类已经在缓存中,则直接取出,否则用ProxyClassFactory创建新代理类
return proxyClassCache.get(loader, interfaces);
}

调用WeakCache的get方法:

private final ReferenceQueue<K> refQueue
        = new ReferenceQueue<>();
/**
* K 表示key
* P 表示parameters
* V 表示value
*/
public V get(K key, P parameter) {
//NullObject判断方法
Objects.requireNonNull(parameter);
//清理持有弱引用的WeakHashMap这种数据结构
expungeStaleEntries();
//从队列中获取cacheKey
Object cacheKey = CacheKey.valueOf(key, refQueue);

调用CacheKey的valueOf

java.lang.ref.Reference
Reference(T referent, ReferenceQueue<? super T> queue) {
        this.referent = referent;
        this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
    } private static final class CacheKey<K> extends WeakReference<K> { // a replacement for null keys
private static final Object NULL_KEY = new Object(); static <K> Object valueOf(K key, ReferenceQueue<K> refQueue) {
return key == null ? NULL_KEY : new CacheKey<>(key, refQueue);
} private final int hash; private CacheKey(K key, ReferenceQueue<K> refQueue) {
super(key, refQueue);
       //返回给定对象的哈希码,
            //该代码与默认的方法 hashCode() 返回的代码一样,无论给定对象的类是否重写 hashCode()。null 引用的哈希码为 0。
this.hash = System.identityHashCode(key);
}

ReferenceQueue的源码先暂时不分析,回到WeakCache中get方法

//利用懒加载的方式获取cacheKey对应的Supplier
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
//如果map中不存在cache键值对,则把cacheKey对应的键值对放进map
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
// subKeyFactory.apply调用Proxy中KeyFactory静态类的apply方法
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
subKeyFactory.apply调用Proxy中KeyFactory静态类的apply方法
 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、Key2、KeyX都是Proxy的内部类

/*
* Key1 and Key2 都是用来给实现了1个或者2个接口的代理类使用
*/
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();
}
} private static final class Key2 extends WeakReference<Class<?>> {
private final int hash;
private final WeakReference<Class<?>> ref2; Key2(Class<?> intf1, Class<?> intf2) {
super(intf1);
hash = 31 * intf1.hashCode() + intf2.hashCode();
ref2 = new WeakReference<Class<?>>(intf2);
} @Override
public int hashCode() {
return hash;
} @Override
public boolean equals(Object obj) {
Class<?> intf1, intf2;
return this == obj ||
obj != null &&
obj.getClass() == Key2.class &&
(intf1 = get()) != null &&
intf1 == ((Key2) obj).get() &&
(intf2 = ref2.get()) != null &&
intf2 == ((Key2) obj).ref2.get();
}
} /*
* 用来给实现了3个或3个以上接口的代理类使用
*/
private static final class KeyX {
private final int hash;
private final WeakReference<Class<?>>[] refs; KeyX(Class<?>[] interfaces) {
hash = Arrays.hashCode(interfaces);
refs = new WeakReference[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
refs[i] = new WeakReference(interfaces[i]);
}
} @Override
public int hashCode() {
return hash;
} @Override
public boolean equals(Object obj) {
return this == obj ||
obj != null &&
obj.getClass() == KeyX.class &&
equals(refs, ((KeyX) obj).refs);
} private static boolean equals(WeakReference<Class<?>>[] refs1,
WeakReference<Class<?>>[] refs2) {
if (refs1.length != refs2.length) {
return false;
}
for (int i = 0; i < refs1.length; i++) {
Class<?> intf = refs1[i].get();
if (intf == null || intf != refs2[i].get()) {
return false;
}
}
return true;
}
}

回到get方法:

//
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null; while (true) {
if (supplier != null) {
//调用Factory实现的get方法,返回实现InvokeHandler的类,并包含了所需要的信息
V value = supplier.get();
if (value != null) {
return value;
}
} //懒加载构建工厂
if (factory == null) {
/**
*创建一个工厂
key classloader
parameter interfaces接口
subkey 存储interfaces的对象
valuesMap cacheKey键值对
*/
factory = new Factory(key, parameter, subKey, valuesMap);
} if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
//填充supplier
supplier = factory;
}
} else {
if (valuesMap.replace(subKey, supplier, factory)) {
supplier = factory;
} else {
supplier = valuesMap.get(subKey);
}
}
}

调用Supplier子类Factory的get方法:

@Override
public synchronized V get() {
// 重新检查supplier
Supplier<V> supplier = valuesMap.get(subKey);
if (supplier != this) {
return null;
} V value = null;
try {
//调用Proxy类种ProxyFactoryClass的apply方法,apply才是真正创建代理类的方法
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)
CacheValue<V> cacheValue = new CacheValue<>(value); // try replacing us with CacheValue (this should always succeed)
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;
}

调用ProxyFactoryClass的apply方法:

private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
//动态代理类的前缀
private static final String proxyClassNamePrefix = "$Proxy"; //最终动态代理类的名字一般都是$ProxyN (N=0,1,2,3,4,5,6,7,8)
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) {
}
//如果使你自己定义的ClassLoader加载的class与你传入的class不一样,则抛出异常
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/*
* 判断Class对象是否是一个接口
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* 验证接口是否重复
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
} String proxyPkg = null; // package to define proxy class in /*
* 检查传入的接口里有没有不是public的接口,如果有,这些接口必须在一个包里
*/
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
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) {
//如果没有非公共的代理接口, 则使用com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
} //为生成的代理类选择一个名字 com.sun.proxy $Proxy0
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num; //生成代理类字节码
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);
try {
//根据代理类的字节码生成代理类的实例
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) { throw new IllegalArgumentException(e.toString());
}
}
}

调用ProxyGenerator.generateProxyClass( proxyName, interfaces);生成接口对应的字节码

public static byte[] generateProxyClass(final String name,
Class[] interfaces)
{
ProxyGenerator gen = new ProxyGenerator(name, interfaces);
//生成字节码
final byte[] classFile = gen.generateClassFile(); if (saveGeneratedFiles) {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
try {
FileOutputStream file =
new FileOutputStream(dotToSlash(name) + ".class");
file.write(classFile);
file.close();
return null;
} catch (IOException e) {
throw new InternalError(
"I/O exception saving generated file: " + e);
}
}
});
} return classFile;
}

调用Proxy.defineClass0本地方法把字节码生成代理类的实例

JDK7动态代理源码分析的更多相关文章

  1. java 1.8 动态代理源码分析

    JDK8动态代理源码分析 动态代理的基本使用就不详细介绍了: 例子: class proxyed implements pro{ @Override public void text() { Syst ...

  2. 动态代理学习(二)JDK动态代理源码分析

    上篇文章我们学习了如何自己实现一个动态代理,这篇文章我们从源码角度来分析下JDK的动态代理 先看一个Demo: public class MyInvocationHandler implements ...

  3. jdk 动态代理源码分析

    闲来无事,撸撸源码 使用方法 直接看代码吧.. package com.test.demo.proxy; import java.lang.reflect.InvocationHandler; imp ...

  4. JDK动态代理源码分析

    先抛出一个问题,JDK的动态代理为什么不支持对实现类的代理,只支持接口的代理??? 首先来看一下如何使用JDK动态代理.JDK提供了Java.lang.reflect.Proxy类来实现动态代理的,可 ...

  5. 设计模式之JDK动态代理源码分析

    这里查看JDK1.8.0_65的源码,通过debug学习JDK动态代理的实现原理 大概流程 1.为接口创建代理类的字节码文件 2.使用ClassLoader将字节码文件加载到JVM 3.创建代理类实例 ...

  6. java动态代理源码解析

    众所周知,java动态代理同反射原理一直是许多框架的底层实现,之前一直没有时间来分析动态代理的底层源码,现结合源码分析一下动态代理的底层实现 类和接口 java动态代理的主要类和接口有:java.la ...

  7. 【趣味设计模式系列】之【代理模式2--JDK动态代理源码解析】

    1. 图解 上图主要描述了JDK动态代理的执行过程,下面做详细分析. 2. Proxy源码分析 上一篇,在使用JDK动态代理的时候,借助于Proxy类,使用newProxyInstance静态方法,创 ...

  8. 【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】

    1. 图解 上图主要描述了Cglib动态代理的主要执行过程,下面做详细分析,以下源码使用的Cglib版本为3.2.12. 2. Enhancer源码分析 public Object create() ...

  9. JDK动态代理源码学习

    继上一篇博客设计模式之代理模式学习之后http://blog.csdn.net/u014427391/article/details/75115928,本博客介绍JDK动态代理的实现原理,学习一下JD ...

随机推荐

  1. Docker下配置双机热备PXC集群

    架构: 步骤: 1.安装centos7   ,设置宿主机IP:192.168.1.224 2.先更新yum软件管理器,再安装docker 1.yum -y update 2.yum install - ...

  2. SpringBoot整合Apache Shiro权限验证框架

    比较常见的权限框架有两种,一种是Spring Security,另一种是Apache Shiro,两种框架各有优劣,个人感觉Shiro更容易使用,更加灵活,也更符合RABC规则,而且是java官方更推 ...

  3. To My Girlfriend (DP)

    题意:求选中若干个数,满足和为S,且不能选中下表i, j 和选中k, l的情况总数量. 思路:DP[i][j][k][l] i:前i个和为j,选中k个和不选中l个的情况数量,那么我们的转换应该是在必选 ...

  4. js 常用代码

    //获取url中的参数 function getUrlParam(name) { var reg = new RegExp("(^|&)" + name + "= ...

  5. Hadoop 安全模式safemode

    启动Hdfs 系统的时候,其中的一个阶段“”安全模式 发生阶段:NameNode启动中,已经读取了fsimage 并且生成了edits 文件,在等待dataNode 向nameNode 发送block ...

  6. 解决SSH远程执行命令找不到环境变量的问题

    通过SSH执行远程主机的命令或脚本时,经常会出现找不到自定义环境变量的问题.但是,如果通过SSH登录远程主机,然后再执行相同的命令或脚本,那么此时执行又是成功的.两种相似的方法,得到的结果却截然不同, ...

  7. 通过Long类型的出生日期算年龄

    package com.utils; import java.text.ParseException; import java.text.SimpleDateFormat; import java.u ...

  8. Eclipse中tomcat启动时报jar包 it's not a class错误;

    Console报错如上: 解决方法: 在Eclipse中Servers文件夹下 对应的项目文件中catalina.properties文件中tomcat.util.scan.DefaultJarSca ...

  9. EDK II代码实例之Variable

    EFI_STATUS Status = EFI_SUCCESS; EFI_GUID OemOSTypeGuid = {0xd06a0bc7, 0x9feb, 0x4cbb, 0xbd, 0x78, 0 ...

  10. 自制操作系统Antz(14)——实现内置编程语言(词法解析器)

    AntzScript