java - @AfterThrowing 没有按预期工作

标签 java spring aop

我想使用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/

相关文章:

java - myeclipse - mysql驱动问题

java - Robospice:在 HTTP 请求正文中发送 JSON 数据

java - AspectJ AOP LTW 不适用于 javaagent 的动态加载

java - spring 3.0 aop 切入点格式不正确 : expecting 'name pattern' error

java - Netbeans 中的 clean 和 build 错误

java - 使用 spring-rabbit 从消息中提取 header ,无需在注释中声明队列

spring - 带有数据源的 applicationContext.xml 或 hibernate.cfg.xml。区别?

spring - 命名 DTO 和实体类

c# - Spring.NET AOP 代理和 MS WebAPI Controller

带有类选择器的javaFX css id选择器不起作用