|
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