您的代码似乎暗示您的方面正在工作,即您的配置的建议执行之前/之后。如果不这样做,其他地方就会出现问题。我进一步假设
- 你的方面按设计工作,并且你已经检查过,
- 您正在使用 Spring AOP,而不是带有加载时编织的 AspectJ,
- 不知何故,GSON 看到的是 CGLIB 代理,而不是底层的原始对象。
那么问题可能是 GSON - 我对它的经验为零,以前从未使用过它 - 使用反射来搜索代理类中的字段。但它不会找到任何代理,因为代理仅重写方法,但没有字段,因为后者位于原始类(代理的父类)中。如果是这样,则需要将 GSON 配置为在原始类中搜索,而不是在代理类中搜索。那么你也不必排除任何东西。
Update:
我上面的有根据的猜测是正确的。
只是因为我很好奇如何从 CGLIB 代理获取原始对象,所以我在调试器中查看了它。似乎每个代理都有一个公共的最终方法getTargetSource
您可以通过反射调用它:
package com.tutorial;
import org.springframework.aop.TargetSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class Application {
public static void main(String[] args) throws Exception {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
ApplicationContext context = new ClassPathXmlApplicationContext("aop.xml");
Student student = (Student) context.getBean("student");
TargetSource targetSource = (TargetSource)
student
.getClass()
.getMethod("getTargetSource", null)
.invoke(student, null);
System.out.println(gson.toJson(targetSource.getTarget()));
}
}
这对我来说适用于你的代码,但我没有在混合中使用 Lombok (你根本没有提到它,我只是在尝试编译你的代码时发现的!),而是手动创建的构造函数、getter 和 setter 只是为了起床和跑步。
此外,您不需要ExclusionStrategy
不再了。
控制台日志:
{
"age": 11,
"name": "Zara"
}
顺便说一句,由于类命名冲突,Lombok 已知会在与 AspectJ 相关时造成麻烦,请参阅我的回答在这里。这也可能会影响 Spring AOP。
我认为你在这里使用了不健康的(因为不兼容的)技术组合,如果你找到了一个解决方案并且不想最终为每个 bean 类编写自定义类型适配器,那么这将是相当糟糕的。如果你删除了 Lombok,至少你可以从 Spring AOP 切换到AspectJ 与 LTW以摆脱代理问题。 AspectJ 不使用代理,因此 GSON 可能会更好地配合它。
更新2:
我的第一次更新只是在茶歇期间进行的快速修改。由于不是 Spring 用户,我也必须先查找 API 文档才能找到接口Advised。它包含方法getTargetSource()
, i.e.:
- 我们可以将 Spring bean(AOP 代理)转换为
Advised
从而避免丑陋的反射。
- 更进一步,我们可以动态确定给定对象是否是(建议的)代理,即如果您更改或停用方面,相同的代码仍然可以工作。
package com.tutorial;
import org.springframework.aop.framework.Advised;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class Application {
public static void main(String[] args) throws Exception {
try (ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("aop.xml")) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Student student = (Student) context.getBean("student");
System.out.println(gson.toJson(unProxy(student)));
}
}
public static Object unProxy(Object object) throws Exception {
return object instanceof Advised
? ((Advised) object).getTargetSource().getTarget()
: object;
}
}
更新3:我很好奇,也为我的 IDE 安装了 Lombok。实际上上面的示例确实可以与 Gson 和我的小unProxy(Object)
方法。所以你可以走了。:-)