JDK动态代理是代理模式的一种实现方式,其只能代理接口。
package com.wish.test;
public interface IndexDao {
public void query();
}
package com.wish.test;
/**
* @program: wish
* @description:
* @author: wang congming
* @create: 2019-12-08 18:18
*/
public class IndexDaoImpl implements IndexDao {
@Override
public void query() {
System.out.println("query");
}
}
package com.wish.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @program: wish
* @description:
* @author: wang congming
* @create: 2019-12-08 18:20
*/
public class TestInvocationHandler implements InvocationHandler {
Object target;
public TestInvocationHandler(Object target){
this.target=target;
}
/**
*
* @param proxy 代理对象
* @param method 目标对象
* @param args 目标方法的参数
* @return
* @throws Throwable
*
*
* proxy logic execute
* target logic execute
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("TestInvocationHandler jdk");
return method.invoke(target,args);
}
}
public static void main(String[] args) {
IndexDao dao = (IndexDao) Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{IndexDao.class},
new TestInvocationHandler(new IndexDaoImpl()));
dao.query();
}
输出结果:
TestInvocationHandler jdk
query
查看 public static Object newProxyInstance(ClassLoader loader,Class>[] interfaces,InvocationHandler h) 方法:
/**
*
* 返回指定接口的代理类的实例,该实例将方法调用调度到指定的处理程序。
*
*
*/
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
//这里是为空校验,可以忽略
Objects.requireNonNull(h);
//将传过来的接口复制一份
final Class>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* 生成对应的代理类
*/
Class> cl = getProxyClass0(loader, intfs);
/*
* 使用自定义的InvocationHandler作为参数,调用构造函数获取代理类对象实例
*/
try {
//校验 ,可以忽略
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//获取构造方法
final Constructor> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
//生成代理对象
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);
}
}
以上是注释过的,源码比较复杂,读源码时,可以从返回值向上看。
1.首先看 return cons.newInstance(new Object[]{h}); 这是生成对象的部分 ,那么可以找找cons 是怎么获取到的,
2.再往上可以找到final Constructor> cons = cl.getConstructor(constructorParams); 这里也就是获取到Constructor 的方法了
3. 构造方法是通过cl 获取到的,那么接着往上找cl ,也就是这行代码 ,Class> cl = getProxyClass0(loader, intfs);
4. 找到方法getProxyClass0,这个方法生成代理类的class文件 ,代码如下:
/**
* 生成代理类。必须先调用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
return proxyClassCache.get(loader, interfaces);
}
可以看出这是一个空壳方法,方法直接调用了proxyClassCache 的get方法。
5. 继续向上看 proxyClassCache是一个全局变量,
private static final WeakCache
6. 查看proxyClassCache 的get方法。
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
expungeStaleEntries();
//从缓存中获取
Object cacheKey = CacheKey.valueOf(key, refQueue);
ConcurrentMap
这段源码很复杂,同样可以从返回值看起
7. 找到返回值,return value; 可以看出value是通过 V value = supplier.get();获取到的,也就是从这里获取到的代理类的class文件
8.那么可以去supplier.get() 方法中查看,这里要注意的是,Supplier具体实现类是Factory,他是WeakCache中的一个私有内部类,idea是无法直接点击过去的,这点可以通过debug看
private final class Factory implements Supplier
9. 查看方法 get()
@Override
public synchronized V get() {
Supplier supplier = valuesMap.get(subKey);
if (supplier != this) {
return null;
}
V value = null;
try {
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // remove us on failure
valuesMap.remove(subKey, this);
}
}
assert value != null;
CacheValue cacheValue = new CacheValue<>(value);
if (valuesMap.replace(subKey, this, cacheValue)) {
reverseMap.put(cacheValue, Boolean.TRUE);
} else {
throw new AssertionError("Should not reach here");
}
return value;
}
这里可以看到 value是通过value = Objects.requireNonNull(valueFactory.apply(key, parameter)); 获取到的
10. Objects.requireNonNull()这个方法主要是进行一个非空校验,valueFactory.apply(key, parameter)这个方法是真正的获取class
这里要注意的是,此方法调用的是类
private static final class ProxyClassFactory implements BiFunction[], Class>>
中的方法 ,代码如下:
@Override
public Class> apply(ClassLoader loader, Class>[] interfaces) {
Map, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class> intf : interfaces) {
/*
* 这里使用传入的classLoader重新加载类,从而判断是不是同一个类
*
*/
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");
}
/*
* 验证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;
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* 这里就是生成代理类包名,
* 这里会判断代理类的接口是否是public,如果不是public则使用,代理接口所在包作为代理类的包名
*
*/
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) {
// public代理接口,使用com.sun.proxy包名
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* 为代理类生成名字 这里会生成一个随机数,这是为了防止并发情况下,类名重复
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* 生成代理类的字节码
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
//这里调用一个native方法将二进制字节码转换为Class
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
这个方法中的重点就是byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags); 生成字节码
return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); 将字节码转换成class
测试代码:
public static void main(String[] args) {
IndexDao dao = (IndexDao) Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{IndexDao.class},
new TestInvocationHandler(new IndexDaoImpl()));
dao.query();
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
"$Proxy88",new Class[]{IndexDao.class});
try {
FileOutputStream fileOutputStream = new FileOutputStream("d:\\$Proxy18.class");
fileOutputStream.write(proxyClassFile);
fileOutputStream.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
生成的是class文件,反编译之后代码如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import com.wish.test.IndexDao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy88 extends Proxy implements IndexDao {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy88(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 void query() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
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 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"));
m3 = Class.forName("com.wish.test.IndexDao").getMethod("query");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
1、代理类继承了Proxy类并且实现了要代理的接口,由于java不支持多继承,所以JDK动态代理不能代理类
2、重写了equals、hashCode、toString
3、有一个静态代码块,通过反射或者代理类的所有方法
4、通过invoke执行代理类中的目标方法query()