Skip to content

Commit 13ba770

Browse files
JoshuaChensnicoll
authored andcommitted
Handle arbitrary JoinPoint argument index
See gh-34316 Signed-off-by: Joshua Chen <[email protected]>
1 parent a4d99d6 commit 13ba770

File tree

2 files changed

+144
-8
lines changed

2 files changed

+144
-8
lines changed

spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -276,14 +276,18 @@ public void setArgumentNamesFromStringArray(String... argumentNames) {
276276
}
277277
if (this.aspectJAdviceMethod.getParameterCount() == this.argumentNames.length + 1) {
278278
// May need to add implicit join point arg name...
279-
Class<?> firstArgType = this.aspectJAdviceMethod.getParameterTypes()[0];
280-
if (firstArgType == JoinPoint.class ||
281-
firstArgType == ProceedingJoinPoint.class ||
282-
firstArgType == JoinPoint.StaticPart.class) {
283-
String[] oldNames = this.argumentNames;
284-
this.argumentNames = new String[oldNames.length + 1];
285-
this.argumentNames[0] = "THIS_JOIN_POINT";
286-
System.arraycopy(oldNames, 0, this.argumentNames, 1, oldNames.length);
279+
for (int i = 0; i < this.aspectJAdviceMethod.getParameterCount(); i++) {
280+
Class<?> argType = this.aspectJAdviceMethod.getParameterTypes()[i];
281+
if (argType == JoinPoint.class ||
282+
argType == ProceedingJoinPoint.class ||
283+
argType == JoinPoint.StaticPart.class) {
284+
String[] oldNames = this.argumentNames;
285+
this.argumentNames = new String[oldNames.length + 1];
286+
System.arraycopy(oldNames, 0, this.argumentNames, 0, i);
287+
this.argumentNames[i] = "THIS_JOIN_POINT";
288+
System.arraycopy(oldNames, i, this.argumentNames, i + 1, oldNames.length - i);
289+
break;
290+
}
287291
}
288292
}
289293
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* Copyright 2002-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.aop.aspectj;
18+
19+
import java.io.Serial;
20+
import java.lang.reflect.Field;
21+
import java.lang.reflect.Method;
22+
import java.util.Arrays;
23+
24+
import org.aspectj.lang.JoinPoint;
25+
import org.aspectj.lang.ProceedingJoinPoint;
26+
import org.jetbrains.annotations.NotNull;
27+
import org.junit.jupiter.api.Test;
28+
29+
import static org.assertj.core.api.Assertions.assertThat;
30+
import static org.mockito.Mockito.mock;
31+
32+
/**
33+
* Tests for {@link AbstractAspectJAdvice}.
34+
*
35+
* @author Joshua Chen
36+
*/
37+
class AbstractAspectJAdviceTests {
38+
39+
@Test
40+
void setArgumentNamesFromStringArray_withJoinPointAsFirstParameter() {
41+
AbstractAspectJAdvice advice = getAspectJAdvice("methodWithJoinPointAsFirstParameter");
42+
assertArgumentNamesFromStringArray(advice);
43+
}
44+
45+
@Test
46+
void setArgumentNamesFromStringArray_withJoinPointAsLastParameter() {
47+
AbstractAspectJAdvice advice = getAspectJAdvice("methodWithJoinPointAsLastParameter");
48+
assertThat(getArgumentNames(advice)[0]).isEqualTo("arg1");
49+
assertThat(getArgumentNames(advice)[1]).isEqualTo("arg2");
50+
assertThat(getArgumentNames(advice)[2]).isEqualTo("THIS_JOIN_POINT");
51+
}
52+
53+
@Test
54+
void setArgumentNamesFromStringArray_withJoinPointAsMiddleParameter() {
55+
AbstractAspectJAdvice advice = getAspectJAdvice("methodWithJoinPointAsMiddleParameter");
56+
assertThat(getArgumentNames(advice)[0]).isEqualTo("arg1");
57+
assertThat(getArgumentNames(advice)[1]).isEqualTo("THIS_JOIN_POINT");
58+
assertThat(getArgumentNames(advice)[2]).isEqualTo("arg2");
59+
}
60+
61+
@Test
62+
void setArgumentNamesFromStringArray_withProceedingJoinPoint() {
63+
AbstractAspectJAdvice advice = getAspectJAdvice("methodWithProceedingJoinPoint");
64+
assertArgumentNamesFromStringArray(advice);
65+
}
66+
67+
@Test
68+
void setArgumentNamesFromStringArray_withStaticPart() {
69+
AbstractAspectJAdvice advice = getAspectJAdvice("methodWithStaticPart");
70+
assertArgumentNamesFromStringArray(advice);
71+
}
72+
73+
private void assertArgumentNamesFromStringArray(AbstractAspectJAdvice advice) {
74+
assertThat(getArgumentNames(advice)[0]).isEqualTo("THIS_JOIN_POINT");
75+
assertThat(getArgumentNames(advice)[1]).isEqualTo("arg1");
76+
assertThat(getArgumentNames(advice)[2]).isEqualTo("arg2");
77+
}
78+
79+
private @NotNull AbstractAspectJAdvice getAspectJAdvice(final String methodName) {
80+
AbstractAspectJAdvice advice = new TestAspectJAdvice(getMethod(methodName), mock(AspectJExpressionPointcut.class), mock(AspectInstanceFactory.class));
81+
advice.setArgumentNamesFromStringArray("arg1", "arg2");
82+
return advice;
83+
}
84+
85+
private Method getMethod(final String name) {
86+
return Arrays.stream(this.getClass().getDeclaredMethods()).filter(m -> m.getName().equals(name)).findFirst().orElseThrow();
87+
}
88+
89+
private String[] getArgumentNames(final AbstractAspectJAdvice advice) {
90+
try {
91+
Field field = AbstractAspectJAdvice.class.getDeclaredField("argumentNames");
92+
field.setAccessible(true);
93+
return (String[]) field.get(advice);
94+
}
95+
catch (NoSuchFieldException | IllegalAccessException e) {
96+
throw new RuntimeException(e);
97+
}
98+
}
99+
100+
public static class TestAspectJAdvice extends AbstractAspectJAdvice {
101+
@Serial private static final long serialVersionUID = 1L;
102+
103+
public TestAspectJAdvice(Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) {
104+
super(aspectJAdviceMethod, pointcut, aspectInstanceFactory);
105+
}
106+
107+
@Override
108+
public boolean isBeforeAdvice() {
109+
return false;
110+
}
111+
112+
@Override
113+
public boolean isAfterAdvice() {
114+
return false;
115+
}
116+
}
117+
118+
void methodWithJoinPointAsFirstParameter(JoinPoint joinPoint, String arg1, String arg2) {
119+
}
120+
121+
void methodWithJoinPointAsLastParameter(String arg1, String arg2, JoinPoint joinPoint) {
122+
}
123+
124+
void methodWithJoinPointAsMiddleParameter(String arg1, JoinPoint joinPoint, String arg2) {
125+
}
126+
127+
void methodWithProceedingJoinPoint(ProceedingJoinPoint joinPoint, String arg1, String arg2) {
128+
}
129+
130+
void methodWithStaticPart(JoinPoint.StaticPart staticPart, String arg1, String arg2) {
131+
}
132+
}

0 commit comments

Comments
 (0)