|
21 | 21 | import java.lang.reflect.Method; |
22 | 22 | import java.util.function.Supplier; |
23 | 23 |
|
| 24 | +import org.aopalliance.aop.Advice; |
| 25 | +import org.aopalliance.intercept.MethodInvocation; |
24 | 26 | import org.aspectj.lang.JoinPoint; |
25 | 27 | import org.aspectj.lang.ProceedingJoinPoint; |
26 | 28 | import org.aspectj.lang.annotation.Around; |
|
31 | 33 | import org.junit.jupiter.params.ParameterizedTest; |
32 | 34 | import org.junit.jupiter.params.provider.ValueSource; |
33 | 35 |
|
| 36 | +import org.springframework.aop.ClassFilter; |
| 37 | +import org.springframework.aop.IntroductionAdvisor; |
| 38 | +import org.springframework.aop.IntroductionInterceptor; |
34 | 39 | import org.springframework.aop.MethodBeforeAdvice; |
| 40 | +import org.springframework.aop.SpringProxy; |
35 | 41 | import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator; |
36 | 42 | import org.springframework.aop.aspectj.annotation.AspectMetadata; |
37 | 43 | import org.springframework.aop.config.AopConfigUtils; |
| 44 | +import org.springframework.aop.framework.Advised; |
38 | 45 | import org.springframework.aop.framework.ProxyConfig; |
| 46 | +import org.springframework.aop.support.AbstractPointcutAdvisor; |
39 | 47 | import org.springframework.aop.support.AopUtils; |
40 | 48 | import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor; |
41 | 49 | import org.springframework.beans.PropertyValue; |
|
52 | 60 | import org.springframework.context.annotation.EnableAspectJAutoProxy; |
53 | 61 | import org.springframework.context.support.ClassPathXmlApplicationContext; |
54 | 62 | import org.springframework.context.support.GenericApplicationContext; |
| 63 | +import org.springframework.core.DecoratingProxy; |
55 | 64 | import org.springframework.core.NestedRuntimeException; |
56 | 65 | import org.springframework.core.Ordered; |
57 | 66 | import org.springframework.core.annotation.Order; |
@@ -304,10 +313,26 @@ public void testWithBeanNameAutoProxyCreator() { |
304 | 313 | @ValueSource(classes = {ProxyTargetClassFalseConfig.class, ProxyTargetClassTrueConfig.class}) |
305 | 314 | void lambdaIsAlwaysProxiedWithJdkProxy(Class<?> configClass) { |
306 | 315 | try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(configClass)) { |
307 | | - Supplier<?> supplier = context.getBean(Supplier.class); |
| 316 | + @SuppressWarnings("unchecked") |
| 317 | + Supplier<String> supplier = context.getBean(Supplier.class); |
308 | 318 | assertThat(AopUtils.isAopProxy(supplier)).as("AOP proxy").isTrue(); |
309 | 319 | assertThat(AopUtils.isJdkDynamicProxy(supplier)).as("JDK Dynamic proxy").isTrue(); |
310 | | - assertThat(supplier.get()).asString().isEqualTo("advised: lambda"); |
| 320 | + assertThat(supplier.getClass().getInterfaces()) |
| 321 | + .containsExactlyInAnyOrder(Supplier.class, SpringProxy.class, Advised.class, DecoratingProxy.class); |
| 322 | + assertThat(supplier.get()).isEqualTo("advised: lambda"); |
| 323 | + } |
| 324 | + } |
| 325 | + |
| 326 | + @ParameterizedTest(name = "[{index}] {0}") |
| 327 | + @ValueSource(classes = {MixinProxyTargetClassFalseConfig.class, MixinProxyTargetClassTrueConfig.class}) |
| 328 | + void lambdaIsAlwaysProxiedWithJdkProxyWithIntroductions(Class<?> configClass) { |
| 329 | + try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(configClass)) { |
| 330 | + MessageGenerator messageGenerator = context.getBean(MessageGenerator.class); |
| 331 | + assertThat(AopUtils.isAopProxy(messageGenerator)).as("AOP proxy").isTrue(); |
| 332 | + assertThat(AopUtils.isJdkDynamicProxy(messageGenerator)).as("JDK Dynamic proxy").isTrue(); |
| 333 | + assertThat(messageGenerator.getClass().getInterfaces()) |
| 334 | + .containsExactlyInAnyOrder(MessageGenerator.class, Mixin.class, SpringProxy.class, Advised.class, DecoratingProxy.class); |
| 335 | + assertThat(messageGenerator.generateMessage()).isEqualTo("mixin: lambda"); |
311 | 336 | } |
312 | 337 | } |
313 | 338 |
|
@@ -616,3 +641,79 @@ class ProxyTargetClassFalseConfig extends AbstractProxyTargetClassConfig { |
616 | 641 | @EnableAspectJAutoProxy(proxyTargetClass = true) |
617 | 642 | class ProxyTargetClassTrueConfig extends AbstractProxyTargetClassConfig { |
618 | 643 | } |
| 644 | + |
| 645 | +@FunctionalInterface |
| 646 | +interface MessageGenerator { |
| 647 | + String generateMessage(); |
| 648 | +} |
| 649 | + |
| 650 | +interface Mixin { |
| 651 | +} |
| 652 | + |
| 653 | +class MixinIntroductionInterceptor implements IntroductionInterceptor { |
| 654 | + |
| 655 | + @Override |
| 656 | + public Object invoke(MethodInvocation invocation) throws Throwable { |
| 657 | + return "mixin: " + invocation.proceed(); |
| 658 | + } |
| 659 | + |
| 660 | + @Override |
| 661 | + public boolean implementsInterface(Class<?> intf) { |
| 662 | + return Mixin.class.isAssignableFrom(intf); |
| 663 | + } |
| 664 | + |
| 665 | +} |
| 666 | + |
| 667 | +@SuppressWarnings("serial") |
| 668 | +class MixinAdvisor extends AbstractPointcutAdvisor implements IntroductionAdvisor { |
| 669 | + |
| 670 | + @Override |
| 671 | + public org.springframework.aop.Pointcut getPointcut() { |
| 672 | + return org.springframework.aop.Pointcut.TRUE; |
| 673 | + } |
| 674 | + |
| 675 | + @Override |
| 676 | + public Advice getAdvice() { |
| 677 | + return new MixinIntroductionInterceptor(); |
| 678 | + } |
| 679 | + |
| 680 | + @Override |
| 681 | + public Class<?>[] getInterfaces() { |
| 682 | + return new Class[] { Mixin.class }; |
| 683 | + } |
| 684 | + |
| 685 | + @Override |
| 686 | + public ClassFilter getClassFilter() { |
| 687 | + return MessageGenerator.class::isAssignableFrom; |
| 688 | + } |
| 689 | + |
| 690 | + @Override |
| 691 | + public void validateInterfaces() { |
| 692 | + /* no-op */ |
| 693 | + } |
| 694 | + |
| 695 | +} |
| 696 | + |
| 697 | +abstract class AbstractMixinConfig { |
| 698 | + |
| 699 | + @Bean |
| 700 | + MessageGenerator messageGenerator() { |
| 701 | + return () -> "lambda"; |
| 702 | + } |
| 703 | + |
| 704 | + @Bean |
| 705 | + MixinAdvisor mixinAdvisor() { |
| 706 | + return new MixinAdvisor(); |
| 707 | + } |
| 708 | + |
| 709 | +} |
| 710 | + |
| 711 | +@Configuration(proxyBeanMethods = false) |
| 712 | +@EnableAspectJAutoProxy(proxyTargetClass = false) |
| 713 | +class MixinProxyTargetClassFalseConfig extends AbstractMixinConfig { |
| 714 | +} |
| 715 | + |
| 716 | +@Configuration(proxyBeanMethods = false) |
| 717 | +@EnableAspectJAutoProxy(proxyTargetClass = true) |
| 718 | +class MixinProxyTargetClassTrueConfig extends AbstractMixinConfig { |
| 719 | +} |
0 commit comments