Я считаю, что ваши ожидания не так (что только один метод перехвата будет соответствовать аналогично перегрузке метода).
Но в то время как RuntimeException
является родителем DataAccessException
оба метода выполняются ...
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<context:component-scan base-package="test" />
<aop:aspectj-autoproxy />
</beans>
AopTest
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AopTest {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring.xml");
MyService ms = ac.getBean(MyService.class);
try {
ms.throw1();
} catch (Exception e) {
// e.printStackTrace();
}
try {
ms.throw2();
} catch (Exception e) {
// e.printStackTrace();
}
}
}
MyAspect
package test;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
@AfterThrowing(pointcut = "execution(public * *(..))", throwing = "ex")
public void intercept(DataAccessException ex) throws Exception {
//throw DatabaseException
System.out.println("DAE");
}
@AfterThrowing(pointcut = "execution(public * *(..))", throwing = "ex")
public void intercept(RuntimeException ex) throws Exception {
//throw ServiceException
System.out.println("RE - " + ex.getClass());
}
}
MyService
package test;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
@Service
public class MyService {
public void throw1() throws DataAccessException {
throw new MyDataAccessException("test");
}
public void throw2() {
throw new NullPointerException();
}
static class MyDataAccessException extends DataAccessException {
public MyDataAccessException(String msg) {
super(msg);
}
}
}
и в журнале есть:
DAE
RE - class test.MyService$MyDataAccessException
RE - class java.lang.NullPointerException
Maven зависимостей:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
From Spring documentation:
Когда две части советов, определенных в том же аспекте, как нужно работать с тем же точкой соединения, порядок не определена (так как нет никакого способа, чтобы получить заказ декларации через отражения для javac- скомпилированные классы). Подумайте о сворачивании таких советов в один советский метод для каждой точки соединения в каждом классе аспектов или реорганизуйте советы в отдельные классы аспектов, которые можно заказать на уровне аспект.
Когда я попытался следующие модификации MyAspect
:
package test;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
@AfterThrowing(pointcut = "execution(public * *(..))", throwing = "ex")
public void intercept(DataAccessException ex) throws Exception {
//throw DatabaseException
System.out.println("DAE");
throw new IllegalArgumentException("DAE"); // added
}
@AfterThrowing(pointcut = "execution(public * *(..))", throwing = "ex")
public void intercept(RuntimeException ex) throws Exception {
//throw ServiceException
System.out.println("RE - " + ex.getClass());
throw new IllegalArgumentException("RE"); // added
}
}
журнал изменен на:
DAE
RE - class java.lang.IllegalArgumentException
RE - class java.lang.NullPointerException
и когда изменен, чтобы Exception
я получил:
package test;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
@AfterThrowing(pointcut = "execution(public * *(..))", throwing = "ex")
public void intercept(DataAccessException ex) throws Exception {
//throw DatabaseException
System.out.println("DAE");
throw new Exception("DAE2"); // changed
}
@AfterThrowing(pointcut = "execution(public * *(..))", throwing = "ex")
public void intercept(RuntimeException ex) throws Exception {
//throw ServiceException
System.out.println("RE - " + ex.getClass());
throw new Exception("RE2"); // changed
}
}
бревно было
DAE
RE - class java.lang.NullPointerException
Я считаю, что решение вашей «проблемы», чтобы иметь два аспекта вместо одного и определяют порядок:
package test;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class DaeAspect implements Ordered {
public int getOrder() {
return 200;
}
@AfterThrowing(pointcut = "execution(public * *(..))", throwing = "ex")
public void intercept(DataAccessException ex) throws Exception {
//throw DatabaseException
System.out.println("DAE");
throw new IllegalAccessException("DAE2"); // based on my testing, this stops second aspect to apply
}
}
и
package test;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class ReAspect implements Ordered {
public int getOrder() {
return 100;
}
@AfterThrowing(pointcut = "execution(public * *(..))", throwing = "ex")
public void intercept(RuntimeException ex) throws Exception {
//throw ServiceException
System.out.println("RE - " + ex.getClass());
throw new IllegalAccessException("RE2");
}
}
Под "неправильный метод" вы имеете в виду, что оба метода выполняются, не так ли? – Betlista
Нет. Только метод 'intercept (RuntimeException). – Francesco
Можете ли вы проверить мой ответ и поделиться тем, что в вашем случае отличается? Вы не использовали Spring версию, определение 'onlyServiceClasses' и другие детали ... – Betlista