Always fall back to original method if annotation pointcut used
Prior to this commit, AspectJExpressionPointcut doesn't fall back to original method if `!@annotation()` is used, it can cause false positive result. Fix GH-27119
This commit is contained in:
parent
16c6376b3f
commit
3a6d0c1d5b
|
|
@ -78,6 +78,7 @@ import org.springframework.util.StringUtils;
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Ramnivas Laddad
|
* @author Ramnivas Laddad
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @author Yanming Zhou
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
|
|
@ -470,8 +471,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||||
fallbackExpression = null;
|
fallbackExpression = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (targetMethod != originalMethod && (shadowMatch == null ||
|
if (targetMethod != originalMethod && (shadowMatch == null || shouldFallback(targetMethod))) {
|
||||||
(shadowMatch.neverMatches() && Proxy.isProxyClass(targetMethod.getDeclaringClass())))) {
|
|
||||||
// Fall back to the plain original method in case of no resolvable match or a
|
// Fall back to the plain original method in case of no resolvable match or a
|
||||||
// negative match on a proxy class (which doesn't carry any annotations on its
|
// negative match on a proxy class (which doesn't carry any annotations on its
|
||||||
// redeclared methods).
|
// redeclared methods).
|
||||||
|
|
@ -513,6 +513,12 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||||
return shadowMatch;
|
return shadowMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean shouldFallback(Method targetMethod) {
|
||||||
|
if (!Proxy.isProxyClass(targetMethod.getDeclaringClass())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.resolveExpression().contains("@annotation");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable Object other) {
|
public boolean equals(@Nullable Object other) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -50,6 +50,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||||
* @author Rob Harrop
|
* @author Rob Harrop
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
|
* @author Yanming Zhou
|
||||||
*/
|
*/
|
||||||
public class AspectJExpressionPointcutTests {
|
public class AspectJExpressionPointcutTests {
|
||||||
|
|
||||||
|
|
@ -424,6 +425,19 @@ public class AspectJExpressionPointcutTests {
|
||||||
assertThat(ajexp.matches(BeanA.class.getMethod("getAge"), proxy.getClass())).isTrue();
|
assertThat(ajexp.matches(BeanA.class.getMethod("getAge"), proxy.getClass())).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNotAnnotationOnCglibProxyMethod() throws Exception {
|
||||||
|
String expression = "!@annotation(test.annotation.transaction.Tx)";
|
||||||
|
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||||
|
ajexp.setExpression(expression);
|
||||||
|
|
||||||
|
ProxyFactory factory = new ProxyFactory(new BeanA());
|
||||||
|
factory.setProxyTargetClass(true);
|
||||||
|
BeanA proxy = (BeanA) factory.getProxy();
|
||||||
|
assertThat(ajexp.matches(BeanA.class.getMethod("getAge"), proxy.getClass())).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAnnotationOnDynamicProxyMethod() throws Exception {
|
public void testAnnotationOnDynamicProxyMethod() throws Exception {
|
||||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||||
|
|
@ -436,6 +450,18 @@ public class AspectJExpressionPointcutTests {
|
||||||
assertThat(ajexp.matches(IBeanA.class.getMethod("getAge"), proxy.getClass())).isTrue();
|
assertThat(ajexp.matches(IBeanA.class.getMethod("getAge"), proxy.getClass())).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNotAnnotationOnDynamicProxyMethod() throws Exception {
|
||||||
|
String expression = "!@annotation(test.annotation.transaction.Tx)";
|
||||||
|
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||||
|
ajexp.setExpression(expression);
|
||||||
|
|
||||||
|
ProxyFactory factory = new ProxyFactory(new BeanA());
|
||||||
|
factory.setProxyTargetClass(false);
|
||||||
|
IBeanA proxy = (IBeanA) factory.getProxy();
|
||||||
|
assertThat(ajexp.matches(IBeanA.class.getMethod("getAge"), proxy.getClass())).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAnnotationOnMethodWithWildcard() throws Exception {
|
public void testAnnotationOnMethodWithWildcard() throws Exception {
|
||||||
String expression = "execution(@(test.annotation..*) * *(..))";
|
String expression = "execution(@(test.annotation..*) * *(..))";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue