Browse Source

Propagate arguments for dynamic prototype-scoped advice

Closes gh-28407
pull/31965/head
Juergen Hoeller 2 years ago
parent
commit
43107e7eb1
  1. 4
      spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java
  2. 49
      spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/ArgumentBindingTests.java
  3. 6
      spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/ITestBean.java

4
spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 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.
@ -293,7 +293,7 @@ final class InstantiationModelAwarePointcutAdvisorImpl
@Override @Override
public boolean matches(Method method, Class<?> targetClass, Object... args) { public boolean matches(Method method, Class<?> targetClass, Object... args) {
// This can match only on declared pointcut. // This can match only on declared pointcut.
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)); return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass, args));
} }
private boolean isAspectMaterialized() { private boolean isAspectMaterialized() {

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

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 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.
@ -42,26 +42,38 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
*/ */
class ArgumentBindingTests { class ArgumentBindingTests {
@Test
void annotationArgumentNameBinding() {
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TransactionalBean());
proxyFactory.addAspect(PointcutWithAnnotationArgument.class);
ITransactionalBean proxiedTestBean = proxyFactory.getProxy();
assertThatIllegalStateException()
.isThrownBy(proxiedTestBean::doInTransaction)
.withMessage("Invoked with @Transactional");
}
@Test @Test
void bindingInPointcutUsedByAdvice() { void bindingInPointcutUsedByAdvice() {
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean()); AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean());
proxyFactory.addAspect(NamedPointcutWithArgs.class); proxyFactory.addAspect(NamedPointcutWithArgs.class);
ITestBean proxiedTestBean = proxyFactory.getProxy(); ITestBean proxiedTestBean = proxyFactory.getProxy();
assertThatIllegalArgumentException() assertThatIllegalArgumentException()
.isThrownBy(() -> proxiedTestBean.setName("enigma")) .isThrownBy(() -> proxiedTestBean.setName("enigma"))
.withMessage("enigma"); .withMessage("enigma");
} }
@Test @Test
void annotationArgumentNameBinding() { void bindingWithDynamicAdvice() {
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TransactionalBean()); AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean());
proxyFactory.addAspect(PointcutWithAnnotationArgument.class); proxyFactory.addAspect(DynamicPointcutWithArgs.class);
ITestBean proxiedTestBean = proxyFactory.getProxy();
ITransactionalBean proxiedTestBean = proxyFactory.getProxy(); proxiedTestBean.applyName(1);
assertThatIllegalStateException() assertThatIllegalArgumentException()
.isThrownBy(proxiedTestBean::doInTransaction) .isThrownBy(() -> proxiedTestBean.applyName("enigma"))
.withMessage("Invoked with @Transactional"); .withMessage("enigma");
} }
@Test @Test
@ -94,6 +106,7 @@ class ArgumentBindingTests {
} }
} }
/** /**
* Mimics Spring's @Transactional annotation without actually introducing the dependency. * Mimics Spring's @Transactional annotation without actually introducing the dependency.
*/ */
@ -101,16 +114,17 @@ class ArgumentBindingTests {
@interface Transactional { @interface Transactional {
} }
@Aspect @Aspect
static class PointcutWithAnnotationArgument { static class PointcutWithAnnotationArgument {
@Around(value = "execution(* org.springframework..*.*(..)) && @annotation(transactional)") @Around("execution(* org.springframework..*.*(..)) && @annotation(transactional)")
public Object around(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable { public Object around(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable {
throw new IllegalStateException("Invoked with @Transactional"); throw new IllegalStateException("Invoked with @Transactional");
} }
} }
@Aspect @Aspect
static class NamedPointcutWithArgs { static class NamedPointcutWithArgs {
@ -121,7 +135,16 @@ class ArgumentBindingTests {
public Object doAround(ProceedingJoinPoint pjp, String aString) throws Throwable { public Object doAround(ProceedingJoinPoint pjp, String aString) throws Throwable {
throw new IllegalArgumentException(aString); throw new IllegalArgumentException(aString);
} }
}
@Aspect("pertarget(execution(* *(..)))")
static class DynamicPointcutWithArgs {
@Around("execution(* *(..)) && args(java.lang.String)")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
throw new IllegalArgumentException(String.valueOf(pjp.getArgs()[0]));
}
} }
} }

6
spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/ITestBean.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2018 the original author or authors. * Copyright 2002-2024 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.
@ -33,6 +33,10 @@ public interface ITestBean extends AgeHolder {
void setName(String name); void setName(String name);
default void applyName(Object name) {
setName(String.valueOf(name));
}
ITestBean getSpouse(); ITestBean getSpouse();
void setSpouse(ITestBean spouse); void setSpouse(ITestBean spouse);

Loading…
Cancel
Save