Exception handling through spring AOP + Aspectj

早过忘川 提交于 2019-12-30 03:25:10

问题


In my project I have a domain layer which is basically POJO and a Spring controller / service layer that is sitting on top of the domain layer. I also have an AOP layer which is sitting between the service and domain.

My domain layer is throwing business exceptions which are now being handled in the service layer.

However I want to change it so that exception thrown from domain layer will be handled in the AOP layer. AOP layer will some kind of error response and send it back to spring controller/ web service layer.

I can create a IBizResponse and make two subclasses/interfaces of it perhaps a SuccessResponse and an ErrorResponse and make my domain layer methods return IBizResponse. However I am not able to figure out how to make AOP return the ErrorResponse object to the service layer.


回答1:


I came across the same scenario where I had to return an error response DTO in case of any exception handling. Inside @Aspect class,

@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());
    }
}

Defined another class for exception handling like below:

@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);
    }
}

Tweeted the code a bit as I cannot share the actual code. Hope I made the concept clear.




回答2:


See After throwing advice section of https://docs.spring.io/spring/docs/4.1.0.RELEASE/spring-framework-reference/htmlsingle/#aop-introduction-defn

After throwing advice runs when a matched method execution exits by throwing an exception. It is declared using the @AfterThrowing annotation:

Examples

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) {
       // ...
     }

}



回答3:


Considering com.sc.bs.impl.* is business/domain layer package and intercepted it in AOP layer using @Around annotation. Code snippet:

@Around("execution(* com.sc.bs.impl..*.*(..))")
public Object exceptionHandlerWithReturnType(ProceedingJoinPoint joinPoint) throws Throwable{
    try {
        obj = joinPoint.proceed();
    } catch(Exception ex) {
        throw ex;
    }
}


来源:https://stackoverflow.com/questions/24797157/exception-handling-through-spring-aop-aspectj

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!