私のプロジェクトには、基本的にPOJOであるドメインレイヤーと、ドメインレイヤーの上にあるSpringコントローラー/サービスレイヤーがあります。また、サービスとドメインの間にあるAOPレイヤーもあります。
私のドメインレイヤーは、現在サービスレイヤーで処理されているビジネス例外をスローしています。
ただし、ドメインレイヤーからスローされた例外がAOPレイヤーで処理されるように変更したいと思います。 AOPレイヤーは、ある種のエラー応答を返し、それをSpring Controller/Webサービスレイヤーに送り返します。
IBizResponseを作成し、その2つのサブクラス/インターフェイスをおそらくSuccessResponseとErrorResponseにして、ドメインレイヤーメソッドにIBizResponseを返すようにすることができます。ただし、AOPがErrorResponseオブジェクトをサービスレイヤーに返すようにする方法を理解できません。
例外処理の場合にエラー応答DTOを返さなければならない同じシナリオに遭遇しました。 @Aspectクラス内では、
@Aspect
@Component
public class MyAspect{
private static final Logger LOGGER = LoggerFactory.getLogger(MyAspect.class);
@Pointcut("execution(* com.linda.dao.strategy.*.*(..))")
public void strategyMethods() { }
@Pointcut("execution(* com.linda.controller.*.*(..)) || execution(* com.linda.Manager.*(..))")
public void controllerMethods(){ }
@Around("strategyMethods()")
public Object profileStrategyMethods(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object output = null;
LOGGER.info("Class:"+pjp.getTarget().getClass()+" entry -> method ->"+pjp.getSignature().getName());
try{
output = pjp.proceed();
long elapsedTime = System.currentTimeMillis() - start;
LOGGER.info("Method execution time: " + elapsedTime + " milliseconds.");
LOGGER.info("Class:"+pjp.getTarget().getClass()+" exit -> method ->"+pjp.getSignature().getName());
}catch(Throwable t){
throw new InternalServerException(t.getMessage());
}
return output;
}
@AfterThrowing(pointcut="execution(* com.linda.dao.strategy.*.*(..)) || execution(* com.linda.controller.*.*(..)) || execution(* com.linda.Manager.*(..))",throwing = "ex")
public void doRecoveryActions(JoinPoint joinPoint, Throwable ex) {
Signature signature = joinPoint.getSignature();
String methodName = signature.getName();
String stuff = signature.toString();
String arguments = Arrays.toString(joinPoint.getArgs());
LOGGER.error("Write something in the log... We have caught exception in method: "
+ methodName + " with arguments "
+ arguments + "\nand the full toString: " + stuff + "\nthe exception is: "
+ ex.getMessage());
}
}
以下のような例外処理用に別のクラスを定義しました。
@ControllerAdvice
public class ExceptionLogAdvice {
@ExceptionHandler(InternalServerException.class)
@ResponseStatus(HttpStatus.BAD_GATEWAY)
@ResponseBody
public ResponseEntity<Object> handleValidationException(final InternalServerException internalServerException){
ErrorResponseDTO dto = constructErrorResponse(internalServerException);
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body(dto);
}
}
実際のコードを共有できないため、コードを少しツイートしました。コンセプトを明確にしたいと思います。
https://docs.spring.io/spring/docs/4.1.0.RELEASE/spring-framework-reference/htmlsingle/#aop-introduction-defn のアドバイスをスローした後のセクションを参照してください。
スロー後のアドバイスは、一致したメソッドの実行が例外をスローして終了したときに実行されます。 @AfterThrowingアノテーションを使用して宣言されます。
例
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
@Aspect
public class AfterThrowingExample {
@AfterThrowing("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doRecoveryActions() {
// ...
}
}
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
@Aspect
public class AfterThrowingExample {
@AfterThrowing(
pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
throwing="ex")
public void doRecoveryActions(DataAccessException ex) {
// ...
}
}
Com.sc.bs.impl。*がビジネス/ドメインレイヤーパッケージであり、@ Aroundアノテーションを使用してAOPレイヤーでインターセプトされていることを考慮してください。コードスニペット:
@Around("execution(* com.sc.bs.impl..*.*(..))")
public Object exceptionHandlerWithReturnType(ProceedingJoinPoint joinPoint) throws Throwable{
try {
obj = joinPoint.proceed();
} catch(Exception ex) {
throw ex;
}
}