获取动态代理类字节码
如果想要拿到动态代理类的源码,需要做以下操作:
在这一行代码前面
Proxy.newProxyInstance(loader, interfaces, h);
添加如下代码
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
完整代码
package jdk代理;
import java.lang.reflect.Proxy;
/***
* @author: claude
* @date: 2023/3/1
* @description:
*/
public class CalculatorProxyFactory{
public static Object getProxy(CalculatorConcrete calculator) {
ClassLoader loader = calculator.getClass().getClassLoader();
Class<?>[] interfaces = calculator.getClass().getInterfaces();
CalculatorInvocationHandler h = new CalculatorInvocationHandler(calculator);
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Object proxy = Proxy.newProxyInstance(loader, interfaces, h);
return proxy;
}
public static void main(String[] args) {
AddAndSubCalculator addAndSubCalculator = (AddAndSubCalculator) getProxy(new CalculatorConcrete());
MultiplyAndDivCalculator multiplyAndDivCalculator = (MultiplyAndDivCalculator) getProxy(new CalculatorConcrete());
addAndSubCalculator.add(1, 1);
System.out.println("----------------------------");
multiplyAndDivCalculator.div(4, 4);
}
}
或者在idea的VM options中 设置如下参数:
-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true
然后生成我们的代理类即可,默认生成的包的路径是:com.sun.proxy。
package jdk代理;
import java.lang.reflect.Proxy;
/***
* @author: claude
* @date: 2023/3/1
* @description:
*/
public class CalculatorProxyFactory{
public static Object getProxy(CalculatorConcrete calculator) {
ClassLoader loader = calculator.getClass().getClassLoader();
Class<?>[] interfaces = calculator.getClass().getInterfaces();
CalculatorInvocationHandler h = new CalculatorInvocationHandler(calculator);
Object proxy = Proxy.newProxyInstance(loader, interfaces, h);
return proxy;
}
public static void main(String[] args) {
AddAndSubCalculator addAndSubCalculator = (AddAndSubCalculator) getProxy(new CalculatorConcrete());
MultiplyAndDivCalculator multiplyAndDivCalculator = (MultiplyAndDivCalculator) getProxy(new CalculatorConcrete());
addAndSubCalculator.add(1, 1);
System.out.println("----------------------------");
multiplyAndDivCalculator.div(4, 4);
}
}
执行完毕之后可以看到生成了1个$Proxy0.class。
反编译动态代理类字节码
将$Proxy0.class直接拖到idea即可反编译。
package com.sun.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import jdk代理.AddAndSubCalculator;
import jdk代理.MultiplyAndDivCalculator;
public final class $Proxy0 extends Proxy implements AddAndSubCalculator, MultiplyAndDivCalculator {
private static Method m1;
private static Method m5;
private static Method m2;
private static Method m3;
private static Method m4;
private static Method m6;
private static Method m0;
public $Proxy0(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 int multiply(int var1, int var2) throws {
try {
return (Integer)super.h.invoke(this, m5, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
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 add(int var1, int var2) throws {
try {
return (Integer)super.h.invoke(this, m3, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
public final int sub(int var1, int var2) throws {
try {
return (Integer)super.h.invoke(this, m4, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
public final int div(int var1, int var2) throws {
try {
return (Integer)super.h.invoke(this, m6, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
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"));
m5 = Class.forName("jdk代理.MultiplyAndDivCalculator").getMethod("multiply", Integer.TYPE, Integer.TYPE);
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("jdk代理.AddAndSubCalculator").getMethod("add", Integer.TYPE, Integer.TYPE);
m4 = Class.forName("jdk代理.AddAndSubCalculator").getMethod("sub", Integer.TYPE, Integer.TYPE);
m6 = Class.forName("jdk代理.MultiplyAndDivCalculator").getMethod("div", Integer.TYPE, Integer.TYPE);
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
动态代理类代码解读
jdk代理原理概览
1.$Proxy0继承自Proxy,在Proxy中有类型为InvocationHandler的成员变量。
protected InvocationHandler h;
Proxy中存在1个带参构造方法,参数是InvocationHandler。
Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
调用$Proxy0的构造方法会调用Proxy的有参构造。从而把自定义的CalculatorInvocationHandler传递给父类。
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
在自定义的CalculatorInvocationHandler中我们定义了一个成员变量calculatorConcrete,为被代理类的实例。
2.调用代理类的add方法,
public static void main(String[] args) {
AddAndSubCalculator addAndSubCalculator = (AddAndSubCalculator) getProxy(new CalculatorConcrete());
addAndSubCalculator.add(1, 1);
}
其实就是调用$Proxy0#add。
生成的代理类$Proxy0会继承Proxy并实现AddAndSubCalculator, MultiplyAndDivCalculator接口。
并重写AddAndSubCalculator, MultiplyAndDivCalculator接口的所有方法。
以add方法为例实现如下:
在生成的代理类Proxy0的成员变量。
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m4;
private static Method m5;
private static Method m6;
private static Method m0;
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("jdk代理.AddAndSubCalculator").getMethod("add", Integer.TYPE, Integer.TYPE);
m4 = Class.forName("jdk代理.AddAndSubCalculator").getMethod("sub", Integer.TYPE, Integer.TYPE);
m5 = Class.forName("jdk代理.MultiplyAndDivCalculator").getMethod("multiply", Integer.TYPE, Integer.TYPE);
m6 = Class.forName("jdk代理.MultiplyAndDivCalculator").getMethod("div", Integer.TYPE, Integer.TYPE);
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
public final int add(int var1, int var2) throws {
try {
//super是Proxy,h是CalculatorInvocationHandler
//this是代理类对象
//m3是接口AddAndSubCalculator#add方法
// new Object[]{var1, var2}是入参
return (Integer)super.h.invoke(this, m3, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
可以看到主要是这一句
//super是Proxy,h是CalculatorInvocationHandler
//this是代理类对象$Proxy0
//m3是接口AddAndSubCalculator#add方法
// new Object[]{var1, var2}是入参
return (Integer)super.h.invoke(this, m3, new Object[]{var1, var2});
由于我们的代理类$Proxy0继承了Proxy,所以我们自定义的CalculatorInvocationHandler可以通过super.h访问到。
所以在调用代理类的方法时,调用的总是CalculatorInvocationHandler的invoke方法。
所以在调用代理类的方法时,调用的总是CalculatorInvocationHandler的invoke方法。
所以在调用代理类的方法时,调用的总是CalculatorInvocationHandler的invoke方法。
5.在CalculatorInvocationHandler#invoke方法中。我们可以使用被代理类的实例CalculatorConcrete通过反射调用到被代理类CalculatorConcrete的原始方法,从而达到在被代理类CalculatorConcrete的方法前后动态织入代码的目的。
public class CalculatorInvocationHandler implements InvocationHandler {
private CalculatorConcrete calculatorConcrete;
public CalculatorInvocationHandler(CalculatorConcrete calculatorConcrete) {
this.calculatorConcrete = calculatorConcrete;
}
//参数1:即代理类对象
//参数2:即m3,是接口AddAndSubCalculator#add方法
//参数3:new Object[]{var1, var2}是入参
//calculatorConcrete是CalculatorInvocationHandler的成员变量
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始计算");
Object result = method.invoke(calculatorConcrete, args);
System.out.println("结束计算:" + result);
return result;
}
}