第一部分:JDK8动态代理基本实现
1,先定义一个接口
public interface UserService {
void work(String workContent);
}
2,再定义一个接口实现类
public class StudentService implements UserService {
@Override
public void work(String workContent) {
System.out.println("StudentService work:" + workContent);
}
}
3,定义最关键的InvocationHandler实现类
public class UserProxyHandler implements InvocationHandler {
UserService realService;
UserService proxyInstance;
public UserProxyHandler(UserService userService) {
realService = userService;
//关键点1:代理实例生成
proxyInstance = (UserService) Proxy.newProxyInstance(getClass().getClassLoader(), userService.getClass().getInterfaces(), this);
}
public UserService getRealService() {
return realService;
}
public UserService getProxyInstance() {
return proxyInstance;
}
// 关键点2:代理实例的接口方法会调用InvocationHandler的invoke方法
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("UserProxyHandler before");
// 代理实现的地方
Object result = method.invoke(realService, objects);
System.out.println("UserProxyHandler after");
return result;
}
}
4,调用代理类,观察代理过程
StudentService studentService = new StudentService();
UserProxyHandler userProxyHandler = new UserProxyHandler(studentService);
userProxyHandler.getProxyInstance().work("proxy go school");
输出结果:
结果分析
整个过程结果都看到,我们明明调用的是代理对象的work方法,但最终还是进入了UserProxyHandler的invoke方法,并通过代理层,调用了真实类的StudentService的work方法。
但是我们还是不清楚JDK到底是如何实现这一步的,其实重点就是2个问题:
- 代理对象是如何产生的
- InvocationHandler的invoke方法具体的怎么调用的
那就老老实实看源码
第二部分:JDK8动态代理原理解析
一,代理对象的产生过程
这部分基本就要看JDK8的源码了,直接IDEA上面一步步,看源码的实现过程,这里只分析重点代码。
Proxy.newProxyInstance方法
将该方法简化后,其实就做了三部:
- 得到代理类的Class对象
- 获得该Class对象的构造函数反射
- 调用构造函数反射生成对象
Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,,InvocationHandler h) {
Class<?> cl = getProxyClass0(loader, intfs);
final Constructor<?> cons = cl.getConstructor(constructorParams);
return cons.newInstance(new Object[]{h});
}
很明显,其中重要的就是第一步,jdk如何得到代理类的Class对象,
该Class对象的生成过程getProxyClass0()。
getProxyClass0()
然而,这个方法内部很简单。
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
return proxyClassCache.get(loader, interfaces);
}
proxyClassCache.get()
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
该方法主要是做了一层内存缓存。具体的Class生成过程其实在ProxyClassFactory里面
缓存过程分析:
get方法首先创建一个valuesMap,获取subKey,里面比较重要的就是subKeyFactory.apply(key,parameter),这个方法会帮我们生成代理类的subKey,之后会建立一个Factory,当使用Factory.get的时候,回去调用valueFactory.apply()
valueFactory即构造函数里面的ProxyClassFactory,便是真正生成代理类的时候。
缓存的思考:
由于第一次的时候需要动态的去创建字节码,然后进行加载,初始化,因此效率和直接new对象相比会比较低下。 这也是使用缓存的原因。虽然有缓存,但是由于使用了WeakReference,GC后有可能会被回收,那么就得重新加载,一定程度上会降低效率,所以一般情况下,我们尽量避免这种动态生成类的方式,而是用在编译时生成类的方式取代,这便是APT技术的精髓。
public V get(K key, P parameter) {
Object cacheKey = CacheKey.valueOf(key, refQueue);
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;
}
}
// create subKey and retrieve the possible Supplier<V> stored by that
// subKey from valuesMap
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
V value = supplier.get();
if (value != null) {
return value;
}
}
// else no supplier in cache
// or a supplier that returned null (could be a cleared CacheValue
// or a Factory that wasn't successful in installing the CacheValue)
// lazily construct a Factory
if (factory == null) {
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
supplier = factory;
}
// else retry with winning supplier
} else {
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
supplier = factory;
} else {
// retry with current supplier
supplier = valuesMap.get(subKey);
}
}
}
}
ProxyClassFactory.apply()
这里面主要五点,
1,利用Class.forName复制一份接口参数传入的接口Class对象
2,拼接Proxy的类名形为: xxx$Proxy0
3,代理类的accessFlags
4,ProxyGenerator.generateProxyClass()获得Class字节码
5,ProxyGenerator.defineClass0() 通过native调用加载字节码,获取Java层Proxy的Class对象
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
Class<?> interfaceClass = null;
interfaceClass = Class.forName(intf.getName(), false, loader);
}
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
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) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* 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);
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
}
至此,代理类的对象生成过程就彻底搞清楚了
二,InvocationHandler的invoke调用时机
我们大胆猜测,具体过程肯定都在ProxyGenerator.generateProxyClass()的生成过程中。
也就是里面的generateClassFile()方法中,此处代码没有注释,只能猜测着看
直接搜索InvocationHandler,很明显发现:
1, generateConstructor 生成了注入InvocationHandler的代理类构造函数
private ProxyGenerator.MethodInfo generateConstructor() throws IOException {
ProxyGenerator.MethodInfo var1 = new ProxyGenerator.MethodInfo("<init>", "(Ljava/lang/reflect/InvocationHandler;)V", 1);
DataOutputStream var2 = new DataOutputStream(var1.code);
this.code_aload(0, var2);
this.code_aload(1, var2);
var2.writeByte(183);
var2.writeShort(this.cp.getMethodRef("java/lang/reflect/Proxy", "<init>", "(Ljava/lang/reflect/InvocationHandler;)V"));
var2.writeByte(177);
var1.maxStack = 10;
var1.maxLocals = 2;
var1.declaredExceptions = new short[0];
return var1;
}
2,ProxyMethod.generateMethod 生成了调用InvocationHandler.invoke的代理接口方法(这里只展示部分代码)
private ProxyGenerator.MethodInfo generateMethod() throws IOException {
String var1 = ProxyGenerator.getMethodDescriptor(this.parameterTypes, this.returnType);
ProxyGenerator.MethodInfo var2 = ProxyGenerator.this.new MethodInfo(this.methodName, var1, 17);
int[] var3 = new int[this.parameterTypes.length];
int var4 = 1;
for(int var5 = 0; var5 < var3.length; ++var5) {
var3[var5] = var4;
var4 += ProxyGenerator.getWordsPerType(this.parameterTypes[var5]);
}
byte var7 = 0;
DataOutputStream var9 = new DataOutputStream(var2.code);
ProxyGenerator.this.code_aload(0, var9);
var9.writeByte(180);
var9.writeShort(ProxyGenerator.this.cp.getFieldRef("java/lang/reflect/Proxy", "h", "Ljava/lang/reflect/InvocationHandler;"));
ProxyGenerator.this.code_aload(0, var9);
var9.writeByte(178);
var9.writeShort(ProxyGenerator.this.cp.getFieldRef(ProxyGenerator.dotToSlash(ProxyGenerator.this.className), this.methodFieldName, "Ljava/lang/reflect/Method;"));
if (this.parameterTypes.length > 0) {
ProxyGenerator.this.code_ipush(this.parameterTypes.length, var9);
var9.writeByte(189);
var9.writeShort(ProxyGenerator.this.cp.getClass("java/lang/Object"));
for(int var10 = 0; var10 < this.parameterTypes.length; ++var10) {
var9.writeByte(89);
ProxyGenerator.this.code_ipush(var10, var9);
this.codeWrapArgument(this.parameterTypes[var10], var3[var10], var9);
var9.writeByte(83);
}
} else {
var9.writeByte(1);
}
var9.writeByte(185);
var9.writeShort(ProxyGenerator.this.cp.getInterfaceMethodRef("java/lang/reflect/InvocationHandler", "invoke", "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"));
var9.writeByte(4);
var9.writeByte(0);
}
我们可以调用ProxyGenerator.generateProxyClass来看一下这个生成的类,把它写到文件里,然后打开验证一下,关键方法如下所示:
public final void work(String var1) throws {
try {
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
至此,谜底全部解开了!!!