Tighten (IntroductionAware)MethodMatcher contract

Provides a non-null guarantee for MethodMatcher's targetClass argument and strict separation between IntroductionAwareMethodMatcher and regular MethodMatcher, enabling DefaultAdvisorChainFactory to defer its IntroductionAdvisor determination until encountering an actual IntroductionAwareMethodMatcher (even behind union/intersection).

Issue: SPR-17068
This commit is contained in:
Juergen Hoeller
2018-07-20 00:17:31 +02:00
parent 867b3d233d
commit 252f52ab07
22 changed files with 170 additions and 103 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2018 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.
@@ -23,8 +23,10 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.aopalliance.intercept.MethodInterceptor;
import org.junit.Test;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -62,6 +64,26 @@ public class AsyncAnnotationBeanPostProcessorTests {
public void invokedAsynchronously() {
ConfigurableApplicationContext context = initContext(
new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class));
ITestBean testBean = context.getBean("target", ITestBean.class);
testBean.test();
Thread mainThread = Thread.currentThread();
testBean.await(3000);
Thread asyncThread = testBean.getThread();
assertNotSame(mainThread, asyncThread);
context.close();
}
@Test
public void invokedAsynchronouslyOnProxyTarget() {
StaticApplicationContext context = new StaticApplicationContext();
context.registerBeanDefinition("postProcessor", new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class));
TestBean tb = new TestBean();
ProxyFactory pf = new ProxyFactory(ITestBean.class,
(MethodInterceptor) invocation -> invocation.getMethod().invoke(tb, invocation.getArguments()));
context.registerBean("target", ITestBean.class, () -> (ITestBean) pf.getProxy());
context.refresh();
ITestBean testBean = context.getBean("target", ITestBean.class);
testBean.test();
Thread mainThread = Thread.currentThread();
@@ -79,6 +101,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
executor.afterPropertiesSet();
processorDefinition.getPropertyValues().add("executor", executor);
ConfigurableApplicationContext context = initContext(processorDefinition);
ITestBean testBean = context.getBean("target", ITestBean.class);
testBean.test();
testBean.await(3000);
@@ -246,8 +269,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
private ConfigurableApplicationContext initContext(BeanDefinition asyncAnnotationBeanPostProcessorDefinition) {
StaticApplicationContext context = new StaticApplicationContext();
BeanDefinition targetDefinition =
new RootBeanDefinition(AsyncAnnotationBeanPostProcessorTests.TestBean.class);
BeanDefinition targetDefinition = new RootBeanDefinition(TestBean.class);
context.registerBeanDefinition("postProcessor", asyncAnnotationBeanPostProcessorDefinition);
context.registerBeanDefinition("target", targetDefinition);
context.refresh();
@@ -259,6 +281,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
Thread getThread();
@Async
void test();
Future<Object> failWithFuture();