diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java index 7d89175c8c2..149cb3b0b0d 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.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"); * you may not use this file except in compliance with the License. @@ -35,7 +35,8 @@ import org.springframework.lang.Nullable; /** * Internal implementation of AspectJPointcutAdvisor. - * Note that there will be one instance of this advisor for each target method. + * + *

Note that there will be one instance of this advisor for each target method. * * @author Rod Johnson * @author Juergen Hoeller @@ -293,7 +294,7 @@ final class InstantiationModelAwarePointcutAdvisorImpl @Override public boolean matches(Method method, Class targetClass, Object... args) { // 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() { diff --git a/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/ArgumentBindingTests.java b/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/ArgumentBindingTests.java index 835f4a4f95c..4bb8f1c984a 100644 --- a/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/ArgumentBindingTests.java +++ b/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/ArgumentBindingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2024 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. @@ -38,56 +38,67 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; * @author Adrian Colyer * @author Juergen Hoeller * @author Chris Beams + * @author Sam Brannen */ -public class ArgumentBindingTests { +class ArgumentBindingTests { @Test - public void testBindingInPointcutUsedByAdvice() { - TestBean tb = new TestBean(); - AspectJProxyFactory proxyFactory = new AspectJProxyFactory(tb); - proxyFactory.addAspect(NamedPointcutWithArgs.class); + 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 + void bindingInPointcutUsedByAdvice() { + AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean()); + proxyFactory.addAspect(NamedPointcutWithArgs.class); ITestBean proxiedTestBean = proxyFactory.getProxy(); - assertThatIllegalArgumentException().isThrownBy(() -> - proxiedTestBean.setName("Supercalifragalisticexpialidocious")); + + assertThatIllegalArgumentException() + .isThrownBy(() -> proxiedTestBean.setName("enigma")) + .withMessage("enigma"); } @Test - public void testAnnotationArgumentNameBinding() { - TransactionalBean tb = new TransactionalBean(); - AspectJProxyFactory proxyFactory = new AspectJProxyFactory(tb); - proxyFactory.addAspect(PointcutWithAnnotationArgument.class); + void bindingWithDynamicAdvice() { + AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean()); + proxyFactory.addAspect(DynamicPointcutWithArgs.class); + ITestBean proxiedTestBean = proxyFactory.getProxy(); - ITransactionalBean proxiedTestBean = proxyFactory.getProxy(); - assertThatIllegalStateException().isThrownBy( - proxiedTestBean::doInTransaction); + proxiedTestBean.applyName(1); + assertThatIllegalArgumentException() + .isThrownBy(() -> proxiedTestBean.applyName("enigma")) + .withMessage("enigma"); } @Test - public void testParameterNameDiscoverWithReferencePointcut() throws Exception { + void parameterNameDiscoverWithReferencePointcut() throws Exception { AspectJAdviceParameterNameDiscoverer discoverer = new AspectJAdviceParameterNameDiscoverer("somepc(formal) && set(* *)"); discoverer.setRaiseExceptions(true); - Method methodUsedForParameterTypeDiscovery = - getClass().getMethod("methodWithOneParam", String.class); - String[] pnames = discoverer.getParameterNames(methodUsedForParameterTypeDiscovery); - assertThat(pnames.length).as("one parameter name").isEqualTo(1); - assertThat(pnames[0]).isEqualTo("formal"); + Method method = getClass().getDeclaredMethod("methodWithOneParam", String.class); + assertThat(discoverer.getParameterNames(method)).containsExactly("formal"); } - public void methodWithOneParam(String aParam) { + @SuppressWarnings("unused") + private void methodWithOneParam(String aParam) { } - public interface ITransactionalBean { + interface ITransactionalBean { @Transactional void doInTransaction(); } - public static class TransactionalBean implements ITransactionalBean { + static class TransactionalBean implements ITransactionalBean { @Override @Transactional @@ -95,38 +106,46 @@ public class ArgumentBindingTests { } } -} -/** - * Represents Spring's Transactional annotation without actually introducing the dependency - */ -@Retention(RetentionPolicy.RUNTIME) -@interface Transactional { -} + /** + * Mimics Spring's @Transactional annotation without actually introducing the dependency. + */ + @Retention(RetentionPolicy.RUNTIME) + @interface Transactional { + } -@Aspect -class PointcutWithAnnotationArgument { + @Aspect + static class PointcutWithAnnotationArgument { - @Around(value = "execution(* org.springframework..*.*(..)) && @annotation(transaction)") - public Object around(ProceedingJoinPoint pjp, Transactional transaction) throws Throwable { - System.out.println("Invoked with transaction " + transaction); - throw new IllegalStateException(); + @Around("execution(* org.springframework..*.*(..)) && @annotation(transactional)") + public Object around(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable { + throw new IllegalStateException("Invoked with @Transactional"); + } } -} + @Aspect + static class NamedPointcutWithArgs { -@Aspect -class NamedPointcutWithArgs { + @Pointcut("execution(* *(..)) && args(s,..)") + public void pointcutWithArgs(String s) {} + + @Around("pointcutWithArgs(aString)") + public Object doAround(ProceedingJoinPoint pjp, String aString) throws Throwable { + throw new IllegalArgumentException(aString); + } + } - @Pointcut("execution(* *(..)) && args(s,..)") - public void pointcutWithArgs(String s) {} - @Around("pointcutWithArgs(aString)") - public Object doAround(ProceedingJoinPoint pjp, String aString) throws Throwable { - System.out.println("got '" + aString + "' at '" + pjp + "'"); - 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])); + } } } + diff --git a/spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/ITestBean.java b/spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/ITestBean.java index 43ce2dd40ed..1fa63057745 100644 --- a/spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/ITestBean.java +++ b/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"); * 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); + default void applyName(Object name) { + setName(String.valueOf(name)); + } + ITestBean getSpouse(); void setSpouse(ITestBean spouse);