JDK动态代理原理探究
代理介绍及实现
JDK动态代理源码解析
实现代码:
public class ServiceProxy implements InvocationHandler {
Object target;
public ServiceProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("do before.");
method.invoke(target, args);
System.out.println("do after");
return null;
}
public Object getTarget() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
}
从上面代码中可以看出,实际生成代理类的是 **Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);** 这段。而 invoke(Object proxy, Method method, Object[] args) 是为在生成代理类时利用反射的原理进行调用,所以在newProxyInstance的入参中,传入的是this
查看 newProxyInstance 源码:
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
final Constructor<?> cons = cl.getConstructor(constructorParams);
....
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
....
}
我把校验什么的都去除掉,只取关键部分。可以看出实际生成代理类的是:
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
在点进去看
/**
* Generate a proxy class. Must call the checkProxyAccess method
* to perform permission checks before calling this.
*/
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);
}
/**
* a cache of proxy classes
*/
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
// WeakCache 类,
final class WeakCache<K, P, V> {
...
// 构造器
public WeakCache(BiFunction<K, P, ?> subKeyFactory,
BiFunction<K, P, V> valueFactory) {
this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
this.valueFactory = Objects.requireNonNull(valueFactory);
}
...
}
上面这段主要是 proxyClassCache 这个缓存,这个缓存什么用?这个缓存主要应该是增加产生代理类的效率的,下次再生成代理类的时候直接通过loader和interfaces去取就行了。那第一次是什么时候存入的那?我们溯回源头:subKeyFactory生成 key值,subKeyFactory通过loader和interfaces生成Key值。
valueFactory 生成代理类,存入缓存中。
看看 ProxyClassFactory 这个类,这个类是个私有的静态内部类
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
.....
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
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());
}
}
}
上面代码,去掉一些校验,主要代码呈现出来 **byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);** 这个类就是产生代理类的类。现在主要是看哪里进行调用的
在来看 proxyClassCache 的get方法
public V get(K key, P parameter) {
...
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
V value = supplier.get();
if (value != null) {
return value;
}
}
....
}
private final class Factory implements Supplier<V> {
@Override
public synchronized V get() { // serialize access
...
V value = null;
try {
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // remove us on failure
valuesMap.remove(subKey, this);
}
}
...
return value;
}
}
上面可看出最终调用生成代码的是 Factory#get() 方法 ,而在 proxyClassCache.get 方法中,factory 赋值给了supplier ,supplier使用get方法完成代理类的创建。
有些绕,但是仔细理一下代码就不难看出动态代理的生成过程。
看看代理类是如何完成代理的,我们手动生成动态代理类的.class文件,然后在进行反编译即可发现端倪:
public interface Service {
void sayHell();
}
/**
* @program: demo
* @description:
* @author: LEMONTREE
* @create: 2018-08-22 21:16
*/
public class JdkProxy implements InvocationHandler {
private Object targt;
public JdkProxy(Object targt) {
this.targt = targt;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("open...");
method.invoke(targt, args);
System.out.println("close..");
return null;
}
public Object getInstance() {
return Proxy.newProxyInstance(targt.getClass().getClassLoader(),
targt.getClass().getInterfaces(), this);
}
}
/**
* @program: demo
* @description:
* @author: LEMONTREE
* @create: 2018-08-21 23:31
*/
public class Main {
public static void main(String[] args) throws IOException {
String proxyName = "com.sun.proxy.$Proxy0.class";
Service service = new ServiceImpl();
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, service.getClass().getInterfaces(), 17);
OutputStream out = new FileOutputStream("D:\\$Proxy0");
InputStream in = new ByteArrayInputStream(proxyClassFile);
byte[] buff = new byte[1024];
int len = 0;
while ((len = in.read(buff))!=-1){
out.write(buff);
}
in.close();
out.close();
}
}
将 $Proxy0.class 文件拖到idea中即可完成反编译,看下代码:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.sun.proxy;
import com.lemontest.test.proxy.Service;
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 Service {
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 void sayHell() throws {
try {
super.h.invoke(this, m3, (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("com.lemontest.test.proxy.Service").getMethod("sayHell");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
这里去除了一些公用方法(toString之类的),可以看出:代理类通过h(InvocationHandler,这里是我们传入的JdkProxy),调用JdkProxy的invoke方法
总结
总结一下,简单来说,其实就是 Proxy.newProxyInstance(targt.getClass().getClassLoader(), targt.getClass().getInterfaces(), this); 这个方法生成代理类,生成的代理类的方法都是通过 InvocationHandler 实现类也就是JdkProxy进行包装过(或说代理过)的方法。为什么是JdkProxy的方法?仔细看JdkProxy类,看出,newProxyInstance 方法最后的入参,传了个this进去。