我正在使用Spring AOP来切入我的控制器方法,并尝试将常见的结构响应返回到前端。 定义应如下所示:
public class CommonResponse {
private String status;
private String message;
private Object data;
}
我还有一个点定义,如下所示:
@Aspect
@Component
public class PostMessageInterceptor {
@Pointcut("within(org.moa.controller.*)")
public void postMessageConvert() {}
@Around("postMessageConvert()")
public CommonResponse modifyResult(ProceedingJoinPoint pjp) {
CommonResponse response = new CommonResponse();
try {
Object result = pjp.proceed();
response.setStatus("success");
response.setData(result);
}catch(Throwable t) {
response.setStatus("failure");
response.setMessage(t.getMessage());
}
return response;
}
}
例如,当控制器返回类型中的方法为Map<String,String>
时,执行modifyResult
后,返回类型已从CommonResponse
转换为Map<String,String>
,则将发生Spring AOP异常java.lang.ClassCastException: CommonResponse cannot be cast to java.util.Map
如果我将此方法的返回类型更改为Object,它将正常工作。
我只想这样设计吗?否则,有什么方法可以实现我的目标而无需修改Object的返回类型。因为感觉很奇怪,所有方法都返回相同的Object类型。
答案 0 :(得分:1)
您不能更改包围方法的返回类型。 JVM的机制不允许这样做(请参见this问题的答案)。
您的方法的调用者会根据原始方法的接口编译其代码,但是在执行您的指令后,该方法将返回不同的类型。应该如何工作?
一种可能性是使用接口并返回由您的建议创建的不同实现,例如:
interface MyReturnType {
int getStatus();
Map<String, String> getData();
}
class MethodReturnType implements MyReturnType {
int getStatus() { throw NotImplementedException(); }
// should never be called; every other method in the interface can be implemented in the exact same way
Map<String, String> getData() { return data; } // I omit the constructor and field decleration here
}
class AdviceReturnType implements MyReturnType {
int status;
Map<String, String> data;
int getStatus() { return status; }
Map<String, String> getData() { return data; }
}
public MyReturnType myAdvicedMethod(...) {
// ...
return new MethodReturnType(myCalculatedData);
}
public Object aroundAdvice(ProceedingJoinPoint pjp) {
MyReturnType retVal = (MyReturnType) pjp.proceed();
// calculate status and stuff
return new AdviceReturnType(retVal.getData(), caluclatedStatus, ...);
}