Я воссоздал вашу ситуацию с простой Java + родной AspectJ, потому что я не пользователь Spring. Но аспект как таковой и его pointcut должны быть одинаковыми в Spring AOP, только аспект также должен быть @Component
.
Несколько холостые классы:
package de.scrum_master.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ResponseBody {}
package de.scrum_master.app;
public class BaseError {
private Exception e;
public BaseError(Exception e) {
this.e= e;
}
public String getMessage() {
return e.getMessage();
}
}
package de.scrum_master.app;
public class ExceptionHandler {
public static BaseError errorResponse(Exception e) {
return new BaseError(e);
}
}
package de.scrum_master.app;
public class BaseResponse<T> {
private String body;
private String error = "OK";
public void setBody(String body) {
this.body = body;
}
public void setError(BaseError be) {
error = be.getMessage();
}
@Override
public String toString() {
return "BaseResponse [body=" + body + ", error=" + error + "]";
}
}
приложение Driver:
Есть две целевые методы, возвращающие BaseResponse<String>
, в основном DOI ng то же, что и ваш метод, исключая случайные исключения, но с обработкой исключений. Наверное, это то, чего вы хотите достичь.
Существует также метод анотера, который не должен быть нацелен на аспект (в качестве отрицательного тестового примера).
package de.scrum_master.app;
import java.util.Random;
public class Application {
private static final Random RANDOM = new Random();
public static void main(String[] args) {
Application application = new Application();
for (int i = 0; i < 5; i++) {
System.out.println(application.doSomething());
System.out.println(application.getSomething());
System.out.println(application.getSomethingElse());
}
}
public String doSomething() {
return "Doing something";
}
public @ResponseBody BaseResponse<String> getSomething() {
BaseResponse<String> response = new BaseResponse<String>();
if (RANDOM.nextBoolean())
throw new RuntimeException("cannot get something");
response.setBody("getting something");
return response;
}
public @ResponseBody BaseResponse<String> getSomethingElse() {
BaseResponse<String> response = new BaseResponse<String>();
if (RANDOM.nextBoolean())
throw new RuntimeException("cannot get something else");
response.setBody("getting something else");
return response;
}
}
Ошибка аспект обработки:
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import de.scrum_master.app.BaseError;
import de.scrum_master.app.BaseResponse;
import de.scrum_master.app.ExceptionHandler;
@Aspect
public class ErrorHandler {
@Around("execution(de.scrum_master.app.BaseResponse<String> *(..))")
public Object handleError(ProceedingJoinPoint thisJoinPoint) throws Throwable {
//System.out.println(thisJoinPoint);
try {
return thisJoinPoint.proceed();
} catch (Exception e) {
BaseError be = ExceptionHandler.errorResponse(e);
BaseResponse<String> response = new BaseResponse<String>();
response.setBody("uh-oh!");
response.setError(be);
return response;
}
}
}
консоли журнала:
Здесь вы можете увидеть красиво, как каждый BaseResponse
либо создается и заполняется кодом приложения промывать или ошибкой обрабатывающий аспект:
Doing something
BaseResponse [body=getting something, error=OK]
BaseResponse [body=uh-oh!, error=cannot get something else]
Doing something
BaseResponse [body=uh-oh!, error=cannot get something]
BaseResponse [body=getting something else, error=OK]
Doing something
BaseResponse [body=getting something, error=OK]
BaseResponse [body=getting something else, error=OK]
Doing something
BaseResponse [body=getting something, error=OK]
BaseResponse [body=getting something else, error=OK]
Doing something
BaseResponse [body=getting something, error=OK]
BaseResponse [body=uh-oh!, error=cannot get something else]
Если вы используете Java8, я бы сделал это с помощью вспомогательного метода, использующего лямбду, это минимальные накладные расходы как в коде, так и во время выполнения, и не нуждается в новой зависимости, такой как AspectJ. Если вы используете Java7 или меньше, AspectJ может быть вариантом, использование 'around()' advice - типичный пример учебника для вашего варианта использования. –
Использование JDK 6. заглянет в ваш совет – DarthVader