- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我想使用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/
我想使用AOP来拦截所有在服务层抛出的运行时异常,并作为领域异常重新抛出。 @Aspect @Component public class ExceptionWrapperInterceptor {
我有一个带有以下签名的方法 我想在捕获切点后记录异常,现在当我执行代码时,它会在控制台上抛出异常打印,然后到达我的切点定义的方法,可能是因为它是 @AfterThoring 注释,但有没有可用的 @B
当我的系统抛出异常时,应该调用下面的方法,但事实并非如此。它仅在我从注释中删除“throwing”并将“Exception”作为参数时才有效: 不起作用: @AfterThrowing(pointcu
我的应用程序类路径中有aspectjrt-1.5.4.jar、aspectjweaver-1.6.1.jar、org.springframework.aop-3.0.5.RELEASE.jar。 我的
我有以下奇怪的行为。 当我使用命名切入点时,建议的方法在 @AfterThrowing 的主体之前运行带注释的方法。但是如果我使用内联切入点 @AfterThrowing带注释的首先运行。 为什么会这
我遇到了一种情况,我想模拟 Web 服务调用。我使用的方法是,如果服务关闭,它会抛出异常。我打算在 spring 中使用 ThrowAdvice AOP 来使用该异常,并希望抑制该异常并用我的虚拟对象
package test.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterThrowin
在 AspectJ 中,我想吞下一个异常。 @Aspect public class TestAspect { @Pointcut("execution(public * *Throwable(..
我有以下内容: @AfterReturning("executionOfTrustedAnnotatedMethod()") public void afterReturningFromTrusted
我在使用 AspectJ 使用自定义注释进行切入点时遇到了奇怪的行为。 我使用的切入点是: @AfterThrowing(pointcut="@annotation(com.core.meta.Not
我们使用 Spring AOP 和 Log4j 来登录我们的应用程序。我在应用程序中实现了@Before、@After、@AfterThrowing 建议。但我面临以下问题: 当 catch bloc
当尝试实现一个负责捕获和记录某种类型错误的 Aspect 时,我最初认为使用 AfterThrowing 建议可以实现这一点。然而,他的建议似乎没有捕捉到异常,而只是提供了一个额外的入口点来处理异常。
我对 AOP 完全陌生。我需要建议来编写正确的切入点。我有一个包含所有服务类的服务包。所有类都实现了 Service界面。这个接口(interface)有一个方法 save(entity) .我的建议
我对 AOP 完全陌生。我需要建议来编写正确的切入点。我有一个包含所有服务类的服务包。所有类都实现了 Service界面。这个接口(interface)有一个方法 save(entity) .我的建议
我正在定义 @pointcut 表达式,如下所示。 @Pointcut( "execution(* com.xyz..*(..)) && " + "!within(is
我是一名优秀的程序员,十分优秀!