前言
JAVA中,现在创建动态代理主要有两种方式,JDK动态代理以及CGLIB动态代理。但是平时我们看不到具体生成的动态代理类它的字节码文件是什么样子的,那么我们今天就记录一下针对这两种方式,如何输出其字节码文件到指定目录,方便我们查看。
JDK动态代理
通过java.lang.System#setProperty方法设置系统属性
sun.misc.ProxyGenerator.saveGeneratedFiles=true
jdk.proxy.ProxyGenerator.saveGeneratedFiles=true
上述属性二者择其一,具体设置哪个需要依照JDK版本进行选择,老版本的前者,新版本的后者,实际选择时可以进入sun.misc.ProxyGenerator类查看boolean类型常量saveGeneratedFiles是取得哪个属性。
CGLIB动态代理
通过java.lang.System#setProperty方法设置系统属性
cglib.debugLocation=指定的字节码输出目录
代码展示
package com.test;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@Slf4j
public class ProxyFilePrintDemo {
public static void main(String[] args) {
proxyByJDK();
proxyByCGLIB();
}
private static void proxyByCGLIB() {
// "./"代表设置到当前项目路径下,可以自行设置指定路径输出
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Calculator.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
log.info("CGLIB代理增强逻辑...");
return methodProxy.invokeSuper(o, objects);
}
});
Calculator calculator = (Calculator) enhancer.create();
System.out.println(calculator.add(1, 2));
}
private static void proxyByJDK() {
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[]{ICalculator.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
});
}
}
interface ICalculator {
int add(int a, int b);
}
class Calculator {
public int add(int a, int b) {
return a + b;
}
}