Java 通过 Spring AOP + Aspectj 进行异常处理
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24797157/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Exception handling through spring AOP + Aspectj
提问by Nitish Raj
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.
在我的项目中,我有一个基本上是 POJO 的域层和一个位于域层之上的 Spring 控制器/服务层。我还有一个位于服务和域之间的 AOP 层。
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.
但是我想改变它,以便从域层抛出的异常将在 AOP 层中处理。AOP 层将某种错误响应并将其发送回 spring 控制器/Web 服务层。
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.
我可以创建一个 IBizResponse 并为其创建两个子类/接口,可能是 SuccessResponse 和 ErrorResponse,并使我的域层方法返回 IBizResponse。但是我无法弄清楚如何让 AOP 将 ErrorResponse 对象返回到服务层。
采纳答案by Linz
I came across the same scenario where I had to return an error response DTO in case of any exception handling. Inside @Aspect class,
我遇到了同样的情况,在发生任何异常处理时,我必须返回错误响应 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());
}
}
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.
由于我无法分享实际代码,因此在推特上发布了一些代码。希望我把概念说清楚了。
回答by vinayknl
See After throwing advice section of https://docs.spring.io/spring/docs/4.1.0.RELEASE/spring-framework-reference/htmlsingle/#aop-introduction-defn
参见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:
当匹配的方法执行通过抛出异常退出时,抛出后通知运行。它是使用 @AfterThrowing 注释声明的:
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) {
// ...
}
}
回答by Nitish Raj
Considering com.sc.bs.impl.* is business/domain layer package and intercepted it in AOP layer using @Around annotation. Code snippet:
考虑到 com.sc.bs.impl.* 是业务/领域层包,在 AOP 层使用 @Around 注解截取。代码片段:
@Around("execution(* com.sc.bs.impl..*.*(..))")
public Object exceptionHandlerWithReturnType(ProceedingJoinPoint joinPoint) throws Throwable{
try {
obj = joinPoint.proceed();
} catch(Exception ex) {
throw ex;
}
}