如何让Lombok+Gson与Spring AOP代理兼容?附Student切面问题解决
解决Lombok + Gson + Spring AOP代理序列化空对象问题
我刚踩了个挺头疼的坑,折腾半天终于搞定了,分享给遇到同样问题的朋友:
场景还原:我有个用Lombok注解简化的
Student类,通过Spring AOP的aop.xml配置了日志切面,还特意排除了main字段。结果发现第一个从容器里取出的StudentBean,用Gson序列化后居然输出空的{},完全看不到实体里的字段值。
问题根源
Spring AOP默认会生成代理对象(JDK动态代理或CGLIB代理),把原始的Student实例包裹在里面。Gson默认只会序列化当前对象的可见字段,而代理对象本身并没有我们定义的Student字段,自然就输出空对象了。
解决办法:剥离代理,拿到真实目标对象
我们可以写个工具方法,把Spring AOP的代理壳剥开,直接获取原始的实体实例,再用Gson序列化就正常了:
- 先写个代理剥离工具类:
import org.springframework.aop.framework.AdvisedSupport; import org.springframework.aop.support.AopUtils; import java.lang.reflect.Field; public class ProxyUnwrapper { @SuppressWarnings("unchecked") public static <T> T getRealTarget(T proxy) throws Exception { // 先判断是不是代理对象,不是的话直接返回 if (!AopUtils.isAopProxy(proxy)) { return proxy; } // 反射拿到代理里的AdvisedSupport对象 Field advisedField = proxy.getClass().getDeclaredField("advised"); advisedField.setAccessible(true); AdvisedSupport advised = (AdvisedSupport) advisedField.get(proxy); // 获取真实的目标对象 Object realTarget = advised.getTargetSource().getTarget(); return (T) realTarget; } }
- 序列化前先处理Bean:
// 从Spring容器获取的是代理后的Student对象 Student studentProxy = applicationContext.getBean(Student.class); // 剥离代理,拿到真实的Student实例 Student realStudent = ProxyUnwrapper.getRealTarget(studentProxy); // 现在序列化就正常了 String json = new Gson().toJson(realStudent);
亲测这个方法有效,序列化后能正确输出Student的字段值,不再是{}了。
内容的提问来源于stack exchange,提问作者Leon
相关产品推荐
相关产品推荐

