@ -18,19 +18,22 @@ package org.springframework.scheduling.annotation;
@@ -18,19 +18,22 @@ package org.springframework.scheduling.annotation;
import java.lang.annotation.Retention ;
import java.lang.annotation.RetentionPolicy ;
import java.util.HashMap ;
import java.util.concurrent.Future ;
import org.junit.Before ;
import org.aopalliance.intercept.MethodInterceptor ;
import org.aopalliance.intercept.MethodInvocation ;
import org.junit.Test ;
import org.springframework.aop.framework.ProxyFactory ;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator ;
import org.springframework.aop.support.DefaultIntroductionAdvisor ;
import org.springframework.beans.factory.FactoryBean ;
import org.springframework.beans.factory.support.RootBeanDefinition ;
import org.springframework.context.ApplicationEvent ;
import org.springframework.context.ApplicationListener ;
import org.springframework.context.support.GenericApplicationContext ;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor ;
import org.springframework.tests.Assume ;
import org.springframework.tests.TestGroup ;
import static org.junit.Assert.* ;
@ -46,10 +49,6 @@ public class AsyncExecutionTests {
@@ -46,10 +49,6 @@ public class AsyncExecutionTests {
private static int listenerConstructed = 0 ;
@Before
public void setUp ( ) {
Assume . group ( TestGroup . PERFORMANCE ) ;
}
@Test
public void asyncMethods ( ) throws Exception {
@ -135,6 +134,46 @@ public class AsyncExecutionTests {
@@ -135,6 +134,46 @@ public class AsyncExecutionTests {
assertEquals ( "20" , future . get ( ) ) ;
}
@Test
public void asyncClassWithPostProcessor ( ) throws Exception {
originalThreadName = Thread . currentThread ( ) . getName ( ) ;
GenericApplicationContext context = new GenericApplicationContext ( ) ;
context . registerBeanDefinition ( "asyncTest" , new RootBeanDefinition ( AsyncClassBean . class ) ) ;
context . registerBeanDefinition ( "asyncProcessor" , new RootBeanDefinition ( AsyncAnnotationBeanPostProcessor . class ) ) ;
context . refresh ( ) ;
AsyncClassBean asyncTest = context . getBean ( "asyncTest" , AsyncClassBean . class ) ;
asyncTest . doSomething ( 10 ) ;
Future < String > future = asyncTest . returnSomething ( 20 ) ;
assertEquals ( "20" , future . get ( ) ) ;
}
@Test
public void asyncClassWithInterface ( ) throws Exception {
originalThreadName = Thread . currentThread ( ) . getName ( ) ;
GenericApplicationContext context = new GenericApplicationContext ( ) ;
context . registerBeanDefinition ( "asyncTest" , new RootBeanDefinition ( AsyncClassBeanWithInterface . class ) ) ;
context . registerBeanDefinition ( "autoProxyCreator" , new RootBeanDefinition ( DefaultAdvisorAutoProxyCreator . class ) ) ;
context . registerBeanDefinition ( "asyncAdvisor" , new RootBeanDefinition ( AsyncAnnotationAdvisor . class ) ) ;
context . refresh ( ) ;
RegularInterface asyncTest = context . getBean ( "asyncTest" , RegularInterface . class ) ;
asyncTest . doSomething ( 10 ) ;
Future < String > future = asyncTest . returnSomething ( 20 ) ;
assertEquals ( "20" , future . get ( ) ) ;
}
@Test
public void asyncClassWithInterfaceAndPostProcessor ( ) throws Exception {
originalThreadName = Thread . currentThread ( ) . getName ( ) ;
GenericApplicationContext context = new GenericApplicationContext ( ) ;
context . registerBeanDefinition ( "asyncTest" , new RootBeanDefinition ( AsyncClassBeanWithInterface . class ) ) ;
context . registerBeanDefinition ( "asyncProcessor" , new RootBeanDefinition ( AsyncAnnotationBeanPostProcessor . class ) ) ;
context . refresh ( ) ;
RegularInterface asyncTest = context . getBean ( "asyncTest" , RegularInterface . class ) ;
asyncTest . doSomething ( 10 ) ;
Future < String > future = asyncTest . returnSomething ( 20 ) ;
assertEquals ( "20" , future . get ( ) ) ;
}
@Test
public void asyncInterface ( ) throws Exception {
originalThreadName = Thread . currentThread ( ) . getName ( ) ;
@ -149,6 +188,46 @@ public class AsyncExecutionTests {
@@ -149,6 +188,46 @@ public class AsyncExecutionTests {
assertEquals ( "20" , future . get ( ) ) ;
}
@Test
public void asyncInterfaceWithPostProcessor ( ) throws Exception {
originalThreadName = Thread . currentThread ( ) . getName ( ) ;
GenericApplicationContext context = new GenericApplicationContext ( ) ;
context . registerBeanDefinition ( "asyncTest" , new RootBeanDefinition ( AsyncInterfaceBean . class ) ) ;
context . registerBeanDefinition ( "asyncProcessor" , new RootBeanDefinition ( AsyncAnnotationBeanPostProcessor . class ) ) ;
context . refresh ( ) ;
AsyncInterface asyncTest = context . getBean ( "asyncTest" , AsyncInterface . class ) ;
asyncTest . doSomething ( 10 ) ;
Future < String > future = asyncTest . returnSomething ( 20 ) ;
assertEquals ( "20" , future . get ( ) ) ;
}
@Test
public void dynamicAsyncInterface ( ) throws Exception {
originalThreadName = Thread . currentThread ( ) . getName ( ) ;
GenericApplicationContext context = new GenericApplicationContext ( ) ;
context . registerBeanDefinition ( "asyncTest" , new RootBeanDefinition ( DynamicAsyncInterfaceBean . class ) ) ;
context . registerBeanDefinition ( "autoProxyCreator" , new RootBeanDefinition ( DefaultAdvisorAutoProxyCreator . class ) ) ;
context . registerBeanDefinition ( "asyncAdvisor" , new RootBeanDefinition ( AsyncAnnotationAdvisor . class ) ) ;
context . refresh ( ) ;
AsyncInterface asyncTest = context . getBean ( "asyncTest" , AsyncInterface . class ) ;
asyncTest . doSomething ( 10 ) ;
Future < String > future = asyncTest . returnSomething ( 20 ) ;
assertEquals ( "20" , future . get ( ) ) ;
}
@Test
public void dynamicAsyncInterfaceWithPostProcessor ( ) throws Exception {
originalThreadName = Thread . currentThread ( ) . getName ( ) ;
GenericApplicationContext context = new GenericApplicationContext ( ) ;
context . registerBeanDefinition ( "asyncTest" , new RootBeanDefinition ( DynamicAsyncInterfaceBean . class ) ) ;
context . registerBeanDefinition ( "asyncProcessor" , new RootBeanDefinition ( AsyncAnnotationBeanPostProcessor . class ) ) ;
context . refresh ( ) ;
AsyncInterface asyncTest = context . getBean ( "asyncTest" , AsyncInterface . class ) ;
asyncTest . doSomething ( 10 ) ;
Future < String > future = asyncTest . returnSomething ( 20 ) ;
assertEquals ( "20" , future . get ( ) ) ;
}
@Test
public void asyncMethodsInInterface ( ) throws Exception {
originalThreadName = Thread . currentThread ( ) . getName ( ) ;
@ -164,6 +243,33 @@ public class AsyncExecutionTests {
@@ -164,6 +243,33 @@ public class AsyncExecutionTests {
assertEquals ( "20" , future . get ( ) ) ;
}
@Test
public void asyncMethodsInInterfaceWithPostProcessor ( ) throws Exception {
originalThreadName = Thread . currentThread ( ) . getName ( ) ;
GenericApplicationContext context = new GenericApplicationContext ( ) ;
context . registerBeanDefinition ( "asyncTest" , new RootBeanDefinition ( AsyncMethodsInterfaceBean . class ) ) ;
context . registerBeanDefinition ( "asyncProcessor" , new RootBeanDefinition ( AsyncAnnotationBeanPostProcessor . class ) ) ;
context . refresh ( ) ;
AsyncMethodsInterface asyncTest = context . getBean ( "asyncTest" , AsyncMethodsInterface . class ) ;
asyncTest . doNothing ( 5 ) ;
asyncTest . doSomething ( 10 ) ;
Future < String > future = asyncTest . returnSomething ( 20 ) ;
assertEquals ( "20" , future . get ( ) ) ;
}
@Test
public void dynamicAsyncMethodsInInterfaceWithPostProcessor ( ) throws Exception {
originalThreadName = Thread . currentThread ( ) . getName ( ) ;
GenericApplicationContext context = new GenericApplicationContext ( ) ;
context . registerBeanDefinition ( "asyncTest" , new RootBeanDefinition ( DynamicAsyncMethodsInterfaceBean . class ) ) ;
context . registerBeanDefinition ( "asyncProcessor" , new RootBeanDefinition ( AsyncAnnotationBeanPostProcessor . class ) ) ;
context . refresh ( ) ;
AsyncMethodsInterface asyncTest = context . getBean ( "asyncTest" , AsyncMethodsInterface . class ) ;
asyncTest . doSomething ( 10 ) ;
Future < String > future = asyncTest . returnSomething ( 20 ) ;
assertEquals ( "20" , future . get ( ) ) ;
}
@Test
public void asyncMethodListener ( ) throws Exception {
originalThreadName = Thread . currentThread ( ) . getName ( ) ;
@ -304,6 +410,28 @@ public class AsyncExecutionTests {
@@ -304,6 +410,28 @@ public class AsyncExecutionTests {
}
public interface RegularInterface {
void doSomething ( int i ) ;
Future < String > returnSomething ( int i ) ;
}
@Async
public static class AsyncClassBeanWithInterface implements RegularInterface {
public void doSomething ( int i ) {
assertTrue ( ! Thread . currentThread ( ) . getName ( ) . equals ( originalThreadName ) ) ;
}
public Future < String > returnSomething ( int i ) {
assertTrue ( ! Thread . currentThread ( ) . getName ( ) . equals ( originalThreadName ) ) ;
return new AsyncResult < String > ( Integer . toString ( i ) ) ;
}
}
@Async
public interface AsyncInterface {
@ -328,6 +456,44 @@ public class AsyncExecutionTests {
@@ -328,6 +456,44 @@ public class AsyncExecutionTests {
}
public static class DynamicAsyncInterfaceBean implements FactoryBean < AsyncInterface > {
private final AsyncInterface proxy ;
public DynamicAsyncInterfaceBean ( ) {
ProxyFactory pf = new ProxyFactory ( new HashMap < > ( ) ) ;
DefaultIntroductionAdvisor advisor = new DefaultIntroductionAdvisor ( new MethodInterceptor ( ) {
@Override
public Object invoke ( MethodInvocation invocation ) throws Throwable {
assertTrue ( ! Thread . currentThread ( ) . getName ( ) . equals ( originalThreadName ) ) ;
if ( Future . class . equals ( invocation . getMethod ( ) . getReturnType ( ) ) ) {
return new AsyncResult < String > ( invocation . getArguments ( ) [ 0 ] . toString ( ) ) ;
}
return null ;
}
} ) ;
advisor . addInterface ( AsyncInterface . class ) ;
pf . addAdvisor ( advisor ) ;
this . proxy = ( AsyncInterface ) pf . getProxy ( ) ;
}
@Override
public AsyncInterface getObject ( ) {
return this . proxy ;
}
@Override
public Class < ? > getObjectType ( ) {
return this . proxy . getClass ( ) ;
}
@Override
public boolean isSingleton ( ) {
return true ;
}
}
public interface AsyncMethodsInterface {
void doNothing ( int i ) ;
@ -360,6 +526,44 @@ public class AsyncExecutionTests {
@@ -360,6 +526,44 @@ public class AsyncExecutionTests {
}
public static class DynamicAsyncMethodsInterfaceBean implements FactoryBean < AsyncMethodsInterface > {
private final AsyncMethodsInterface proxy ;
public DynamicAsyncMethodsInterfaceBean ( ) {
ProxyFactory pf = new ProxyFactory ( new HashMap < > ( ) ) ;
DefaultIntroductionAdvisor advisor = new DefaultIntroductionAdvisor ( new MethodInterceptor ( ) {
@Override
public Object invoke ( MethodInvocation invocation ) throws Throwable {
assertTrue ( ! Thread . currentThread ( ) . getName ( ) . equals ( originalThreadName ) ) ;
if ( Future . class . equals ( invocation . getMethod ( ) . getReturnType ( ) ) ) {
return new AsyncResult < String > ( invocation . getArguments ( ) [ 0 ] . toString ( ) ) ;
}
return null ;
}
} ) ;
advisor . addInterface ( AsyncMethodsInterface . class ) ;
pf . addAdvisor ( advisor ) ;
this . proxy = ( AsyncMethodsInterface ) pf . getProxy ( ) ;
}
@Override
public AsyncMethodsInterface getObject ( ) {
return this . proxy ;
}
@Override
public Class < ? > getObjectType ( ) {
return this . proxy . getClass ( ) ;
}
@Override
public boolean isSingleton ( ) {
return true ;
}
}
public static class AsyncMethodListener implements ApplicationListener < ApplicationEvent > {
@Override