Test status quo for invocation order of all advice types

Prior to this commit we did not have tests in place to verify the status
quo for the invocation order of all advice types when declared within
a single aspect, either via the <aop:aspect> XML namespace or AspectJ
auto-proxy support.

This commit introduces such tests that demonstrate where such ordering
is broken or suboptimal.

The only test for which the advice invocation order is correct or at
least as expected is the afterAdviceTypes() test method in
ReflectiveAspectJAdvisorFactoryTests, where an AOP proxy is hand crafted
using ReflectiveAspectJAdvisorFactory without the use of Spring's
AspectJPrecedenceComparator.

See gh-25186
This commit is contained in:
Sam Brannen
2020-06-05 15:22:27 +02:00
parent 04c8de4e50
commit fbeecf3bf8
7 changed files with 124 additions and 44 deletions

View File

@@ -455,7 +455,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
TestBean target = new TestBean();
UnsupportedOperationException expectedException = new UnsupportedOperationException();
List<Advisor> advisors = getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException), "someBean"));
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionThrowingAspect(expectedException), "someBean"));
assertThat(advisors.size()).as("One advice method was found").isEqualTo(1);
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(
@@ -469,7 +469,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
TestBean target = new TestBean();
RemoteException expectedException = new RemoteException();
List<Advisor> advisors = getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException), "someBean"));
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionThrowingAspect(expectedException), "someBean"));
assertThat(advisors.size()).as("One advice method was found").isEqualTo(1);
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
assertThatExceptionOfType(UndeclaredThrowableException.class).isThrownBy(
@@ -510,18 +510,18 @@ abstract class AbstractAspectJAdvisorFactoryTests {
@Test
void afterAdviceTypes() throws Exception {
ExceptionHandling aspect = new ExceptionHandling();
InvocationTrackingAspect aspect = new InvocationTrackingAspect();
List<Advisor> advisors = getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(aspect, "exceptionHandlingAspect"));
Echo echo = (Echo) createProxy(new Echo(), advisors, Echo.class);
assertThat(aspect.invocations).isEmpty();
assertThat(echo.echo(42)).isEqualTo(42);
assertThat(aspect.invocations).containsExactly("after returning", "after");
assertThat(aspect.invocations).containsExactly("around - start", "before", "after returning", "after", "around - end");
aspect.invocations.clear();
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() -> echo.echo(new FileNotFoundException()));
assertThat(aspect.invocations).containsExactly("after throwing", "after");
assertThat(aspect.invocations).containsExactly("around - start", "before", "after throwing", "after", "around - end");
}
@Test
@@ -742,11 +742,11 @@ abstract class AbstractAspectJAdvisorFactoryTests {
@Aspect
static class ExceptionAspect {
static class ExceptionThrowingAspect {
private final Exception ex;
ExceptionAspect(Exception ex) {
ExceptionThrowingAspect(Exception ex) {
this.ex = ex;
}
@@ -769,7 +769,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
@Aspect
static class ExceptionHandling {
private static class InvocationTrackingAspect {
List<String> invocations = new ArrayList<>();
@@ -778,13 +778,29 @@ abstract class AbstractAspectJAdvisorFactoryTests {
void echo() {
}
@Around("echo()")
Object around(ProceedingJoinPoint joinPoint) throws Throwable {
invocations.add("around - start");
try {
return joinPoint.proceed();
}
finally {
invocations.add("around - end");
}
}
@Before("echo()")
void before() {
invocations.add("before");
}
@AfterReturning("echo()")
void succeeded() {
void afterReturning() {
invocations.add("after returning");
}
@AfterThrowing("echo()")
void failed() {
void afterThrowing() {
invocations.add("after throwing");
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import test.aop.PerTargetAspect;
import org.springframework.aop.Pointcut;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.AspectJExpressionPointcutTests;
import org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactoryTests.ExceptionThrowingAspect;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.beans.testfixture.beans.TestBean;
@@ -44,7 +45,7 @@ public class AspectJPointcutAdvisorTests {
InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(
ajexp, TestBean.class.getMethod("getAge"), af,
new SingletonMetadataAwareAspectInstanceFactory(new AbstractAspectJAdvisorFactoryTests.ExceptionAspect(null), "someBean"),
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionThrowingAspect(null), "someBean"),
1, "someBean");
assertThat(ajpa.getAspectMetadata().getPerClausePointcut()).isSameAs(Pointcut.TRUE);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@ import test.aop.PerTargetAspect;
import org.springframework.aop.Pointcut;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactoryTests.ExceptionAspect;
import org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactoryTests.ExceptionThrowingAspect;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@@ -42,7 +42,7 @@ class AspectMetadataTests {
@Test
void singletonAspect() {
AspectMetadata am = new AspectMetadata(ExceptionAspect.class, "someBean");
AspectMetadata am = new AspectMetadata(ExceptionThrowingAspect.class, "someBean");
assertThat(am.isPerThisOrPerTarget()).isFalse();
assertThat(am.getPerClausePointcut()).isSameAs(Pointcut.TRUE);
assertThat(am.getAjType().getPerClause().getKind()).isEqualTo(PerClauseKind.SINGLETON);