jdk的动态代理依赖接口,需要被代理对象实现了一个接口。 jdk的动态代理主要分为3部分。
1、被代理对象:实际去执行对象;
2、InvocationHandler:生成代理对象,在调用真实对象前后做一些功能增强。比如redis释放连接,统计方法时延等;
3、代理对象:这个对象是在jvm运行期间生成的,可以通过sun.misc.ProxyGenerator#generateProxyClass(java.lang.String, java.lang.Class>[]) 生成代理对象的字节码文件,然后反编译工具查看代理类的代码。
调用顺序依次为:
1.生成代理对象;
2.调用代理对象方法;
3.调用java.lang.reflect.InvocationHandler#invoke,传入Method对象;
3.InvocationHandler通过反射调用真实对象。
伪代码:
package org.example.demo;
public interface MyInterface {
void doSth();
}
package org.example.demo;
public class TargetClass implements MyInterface {
@Override
public void doSth() {
System.out.println("target object execute.");
}
}
package org.example.demo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHandler implements InvocationHandler {
private MyInterface targetClass;
private ProxyInvocationHandler(MyInterface targetClass) {
this.targetClass = targetClass;
}
public static MyInterface getInstance() {
return (MyInterface) Proxy.newProxyInstance(ProxyInvocationHandler.class.getClassLoader(),
new Class[]{MyInterface.class}, new ProxyInvocationHandler(new TargetClass()));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("start to invoke target object.");
method.invoke(targetClass, args);
System.out.println("end to invoke target object.");
return null;
}
}
package org.example.demo;
import sun.misc.ProxyGenerator;
import java.io.FileOutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
public class Demo {
public static void main(String[] args) {
ProxyInvocationHandler.getInstance().doSth();
generateProxyClass("ProxyClass", TargetClass.class.getInterfaces(),
Objects.requireNonNull(TargetClass.class.getClassLoader().getResource("")).getPath().substring(1));
}
private static void generateProxyClass(String className, Class>[] interfaces, String pathdir) {
byte[] classFile = ProxyGenerator.generateProxyClass(className, interfaces);
Path path1 = Paths.get(pathdir);
if (!path1.toFile().exists()) {
path1.toFile().mkdirs();
}
String path = pathdir + className + ".class";
try (FileOutputStream fos = new FileOutputStream(path)) {
fos.write(classFile);
fos.flush();
} catch (Exception e) {
}
}
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import org.example.demo.MyInterface;
public final class ProxyClass extends Proxy implements MyInterface {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public ProxyClass(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 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 void doSth() throws {
try {
super.h.invoke(this, m3, (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"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("org.example.demo.MyInterface").getMethod("doSth");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}