Почему нельзя изменить тип ответа с помощью Spring AOP, кроме return Object - PullRequest
0 голосов
/ 04 декабря 2018

Я использую 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>, после *При выполнении 1008 * тип возврата имеет значение CommonResponse с Map<String,String>, тогда в Spring AOP возникнет исключение java.lang.ClassCastException: CommonResponse cannot be cast to java.util.Map

Если я изменю тип возврата этого метода на Object, он будет работать нормально.

Я просто хочу, это так задумано?В противном случае, есть ли способ, которым я могу достичь этой цели без изменения типа возвращаемого значения для объекта.Поскольку это кажется странным, все методы возвращают один и тот же тип объекта.

1 Ответ

0 голосов
/ 04 декабря 2018

вы не можете изменить тип возвращаемого значения окруженного метода.Механика JVM не позволяет этого (см. Ответ на этот вопрос).

Вызывающий ваш метод компилирует свой код с интерфейсом исходного метода, но после выполнения вашего совета метод возвращает другой тип.Как это должно работать?

Можно использовать интерфейс и вернуть другую реализацию, созданную по вашему совету, например:

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, ...);
}
...