我想使用AOP来拦截所有在服务层抛出的运行时异常,并作为领域异常重新抛出。
@Aspect
@Component
public class ExceptionWrapperInterceptor {
@Pointcut("within(*.service.*)")
public void onlyServiceClasses() {}
@AfterThrowing(pointcut = "onlyServiceClasses()", throwing = "ex")
public void intercept(DataAccessException ex) throws Exception {
//throw DatabaseException
}
@AfterThrowing(pointcut = "onlyServiceClasses()", throwing = "ex")
public void intercept(RuntimeException ex) throws Exception {
//throw ServiceException
}
}
这里的问题是,对于 DataAccessException 的子类,运行时会执行错误的方法。有一个优雅的解决方案吗?
Spring 版本:4.2.4.RELEASE
附言具有大量 instanceof 的单个通用方法(从其他问题中读取)对我来说并不优雅;-)
谢谢 弗朗切斯科
最佳答案
如何使用 @Around
建议?您可以在其中简单地使用类型安全的 try-catch
,无需使用任何 instanceof
或反射。
这是我使用 AspectJ 而不是 Spring AOP 编译的一些示例代码,因为我不是 Spring 用户。无论如何,切入点应该是相同的。
辅助类:
package de.scrum_master.service;
public class DatabaseException extends RuntimeException {
public DatabaseException(Throwable arg0) {
super(arg0);
}
}
package de.scrum_master.service;
public class ServiceException extends RuntimeException {
public ServiceException(Throwable arg0) {
super(arg0);
}
}
驱动程序应用程序(纯 Java,无需使用 Spring):
package de.scrum_master.service;
import java.util.Random;
import org.springframework.jdbc.datasource.init.ScriptParseException;
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 < 10; i++) {
try {
application.doSomething();
}
catch (Exception e) {
System.out.println(e);
}
}
}
public void doSomething() {
switch (RANDOM.nextInt(3)) {
case 1: throw new ScriptParseException("uh-oh", null);
case 2: throw new IllegalArgumentException("WTF");
default: System.out.println("doing something");
}
}
}
看点:
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
import de.scrum_master.service.DatabaseException;
import de.scrum_master.service.ServiceException;
@Aspect
@Component
public class ExceptionWrapperInterceptor {
@Pointcut("within(*..service..*) && execution(* *(..))")
public void onlyServiceClasses() {}
@Around("onlyServiceClasses()")
public Object intercept(ProceedingJoinPoint thisJoinPoint) {
try {
return thisJoinPoint.proceed();
}
catch (DataAccessException dae) {
throw new DatabaseException(dae);
}
catch (RuntimeException re) {
throw new ServiceException(re);
}
}
}
控制台日志:
doing something
de.scrum_master.service.DatabaseException: org.springframework.jdbc.datasource.init.ScriptParseException: Failed to parse SQL script from resource [<unknown>]: uh-oh
doing something
de.scrum_master.service.DatabaseException: org.springframework.jdbc.datasource.init.ScriptParseException: Failed to parse SQL script from resource [<unknown>]: uh-oh
doing something
de.scrum_master.service.ServiceException: java.lang.IllegalArgumentException: WTF
de.scrum_master.service.ServiceException: java.lang.IllegalArgumentException: WTF
de.scrum_master.service.ServiceException: java.lang.IllegalArgumentException: WTF
de.scrum_master.service.ServiceException: java.lang.IllegalArgumentException: WTF
doing something
关于java - @AfterThrowing 没有按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34614073/