如何查看/反编译Hibernate JPA生成的@Entity代理类?
完全不用折腾修改Hibernate源码!有几个简单直接的方式就能拿到这些代理类,甚至能反编译看具体实现,我帮你梳理清楚:
1. 让Hibernate直接输出代理类字节码文件
Hibernate默认用ByteBuddy(旧版本用Javassist)生成代理类,我们可以通过配置参数让它把生成的.class文件保存到本地:
针对ByteBuddy(Hibernate 5.2+ 默认)
在persistence.xml或者Hibernate配置文件里添加以下参数:
hibernate.bytecode.bytebuddy.debug=true hibernate.bytecode.bytebuddy.dumpDirectory=/你指定的输出目录路径
启动应用后,所有生成的代理类字节码文件都会被输出到你设置的目录里,之后用JD-GUI、Luyten这类反编译工具就能直接查看代码了。
针对旧版Javassist(Hibernate 5.2以前)
如果项目还在使用Javassist作为字节码提供者,添加这个配置:
javassist.debug=true
代理类字节码会默认输出到项目根目录,也可以通过javassist.dump.dir参数指定自定义路径。
2. 运行时动态转储代理类字节码
不想改配置的话,也可以在代码里通过反射获取代理类的字节码并写入文件,示例代码如下:
import org.hibernate.proxy.HibernateProxy; import java.io.FileOutputStream; import java.lang.reflect.Method; public class ProxyDumper { public static void dumpProxy(Object entity) throws Exception { if (entity instanceof HibernateProxy) { HibernateProxy proxy = (HibernateProxy) entity; Class<?> proxyClass = proxy.getClass(); // 通过反射获取类字节码 Method getBytesMethod = Class.class.getDeclaredMethod("getRawClassBytes"); getBytesMethod.setAccessible(true); byte[] classBytes = (byte[]) getBytesMethod.invoke(proxyClass); // 写入本地文件 String fileName = proxyClass.getSimpleName() + ".class"; try (FileOutputStream fos = new FileOutputStream(fileName)) { fos.write(classBytes); System.out.println("代理类字节码已保存到: " + fileName); } } else { System.out.println("该对象不是Hibernate代理实例"); } } }
当你从JPA拿到代理对象后,调用这个方法就能把字节码保存下来,后续反编译查看即可。
3. 用IDE调试功能直接查看
在IntelliJ IDEA、Eclipse这类IDE里调试时,拿到代理对象后可以在调试窗口看到它的类名(通常是你的实体类名$$EnhancerBySpringCGLIB$$xxxx或你的实体类名$$_jvstxxxx_xxxx这类格式),然后用IDE的「Show Bytecode」功能直接查看字节码,部分IDE还支持一键反编译为Java代码,非常直观。
顺带提一句:这些代理类大多会继承你的实体类,重写getId()或关联属性的getter方法,以此实现懒加载、缓存等Hibernate核心特性,第一次调用时才会触发数据库查询。
内容的提问来源于stack exchange,提问作者tucuxi

