Mikel Hamer 17 hours ago committed by GitHub
parent
commit
6964d4cc3b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 38
      spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java
  2. 49
      spring-aop/src/test/java/org/springframework/aop/aspectj/AspectJExpressionPointcutTests.java

38
spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.aop.aspectj;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@ -459,6 +460,43 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut @@ -459,6 +460,43 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
}
}
else if (containsAnnotationPointcut()) {
try {
// Get the param value inside @annotation(...)
PointcutExpression pointcutExpression = obtainPointcutExpression();
String expr = pointcutExpression.getPointcutExpression();
int start = expr.indexOf('(', expr.indexOf("@annotation"));
int end = expr.indexOf(')', start);
String annotationParam = expr.substring(start + 1, end).trim();
boolean isParamFullyQualifiedClassName = annotationParam.contains(".");
if (isParamFullyQualifiedClassName) {
@SuppressWarnings("unchecked")
Class<? extends Annotation> annClass = (Class<? extends Annotation>) ClassUtils.forName(
annotationParam, targetClass.getClassLoader());
// Check for annotation on target method for every interface in the target class hierarchy
for (Class<?> ifc : ClassUtils.getAllInterfacesForClassAsSet(targetClass)) {
try {
Method interfaceMethod = ifc.getMethod(method.getName(), method.getParameterTypes());
if (interfaceMethod.isAnnotationPresent(annClass)) {
targetMethod = interfaceMethod;
break;
}
}
catch (NoSuchMethodException ignored) {
// The interface doesn't contain the target method
}
}
}
else {
// TODO: Support variable annotation params such as @annotation(transactional)
// WIP gh-22311
}
}
catch (ClassNotFoundException ignored) {
// Pointcut annotation class not found. Proceed with original target method
}
}
return getShadowMatch(targetMethod, method);
}

49
spring-aop/src/test/java/org/springframework/aop/aspectj/AspectJExpressionPointcutTests.java

@ -23,7 +23,11 @@ import java.util.Map; @@ -23,7 +23,11 @@ import java.util.Map;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import test.annotation.EmptySpringAnnotation;
import test.annotation.transaction.Tx;
@ -31,6 +35,7 @@ import test.annotation.transaction.Tx; @@ -31,6 +35,7 @@ import test.annotation.transaction.Tx;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.testfixture.beans.IOther;
@ -513,6 +518,27 @@ class AspectJExpressionPointcutTests { @@ -513,6 +518,27 @@ class AspectJExpressionPointcutTests {
ProcessesSpringAnnotatedParameters.class)).isFalse();
}
@Test
void testAnnotationOnInterfaceMethodWithFQN() throws Exception {
String expression = "@annotation(test.annotation.transaction.Tx)";
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setExpression(expression);
assertThat(ajexp.matches(BeanC.class.getMethod("getAge"), BeanC.class)).isTrue();
}
@Disabled("WIP gh-22311")
@Test
void testAnnotationOnInterfaceMethodWithAnnotationArgument() {
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new BeanC());
proxyFactory.addAspect(PointcutWithTxAnnotationArgument.class);
IBeanC proxiedTestBean = proxyFactory.getProxy();
assertThatIllegalStateException()
.isThrownBy(proxiedTestBean::getAge)
.withMessage("Invoked with @Tx");
}
public static class OtherIOther implements IOther {
@ -602,6 +628,29 @@ class AspectJExpressionPointcutTests { @@ -602,6 +628,29 @@ class AspectJExpressionPointcutTests {
}
}
interface IBeanC {
@Tx
int getAge();
}
static class BeanC implements IBeanC {
@Override
public int getAge() {
return 0;
}
}
@Aspect
static class PointcutWithTxAnnotationArgument {
@Around("@annotation(tx)")
public Object around(ProceedingJoinPoint pjp, Tx tx) {
throw new IllegalStateException("Invoked with @Tx");
}
}
}

Loading…
Cancel
Save