diff --git a/org.springframework.context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessor.java b/org.springframework.context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessor.java index e08a993c98b..93672399b51 100644 --- a/org.springframework.context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessor.java +++ b/org.springframework.context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessor.java @@ -25,8 +25,7 @@ import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanClassLoaderAware; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.Ordered; import org.springframework.core.task.TaskExecutor; @@ -55,7 +54,7 @@ import java.util.concurrent.Executor; * @see AsyncAnnotationAdvisor */ public class AsyncAnnotationBeanPostProcessor extends ProxyConfig - implements BeanPostProcessor, BeanClassLoaderAware, BeanFactoryAware, Ordered { + implements BeanPostProcessor, BeanClassLoaderAware, InitializingBean, Ordered { private Class asyncAnnotationType; @@ -91,7 +90,7 @@ public class AsyncAnnotationBeanPostProcessor extends ProxyConfig this.beanClassLoader = classLoader; } - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + public void afterPropertiesSet() { this.asyncAnnotationAdvisor = (this.executor != null) ? new AsyncAnnotationAdvisor(this.executor) : new AsyncAnnotationAdvisor(); if (this.asyncAnnotationType != null) { @@ -121,7 +120,7 @@ public class AsyncAnnotationBeanPostProcessor extends ProxyConfig // Can't do much here. return bean; } - + if (AopUtils.canApply(this.asyncAnnotationAdvisor, targetClass)) { if (bean instanceof Advised) { ((Advised) bean).addAdvisor(this.asyncAnnotationAdvisor); diff --git a/org.springframework.context/src/test/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessorTests.java b/org.springframework.context/src/test/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessorTests.java new file mode 100644 index 00000000000..532b8328ce6 --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessorTests.java @@ -0,0 +1,122 @@ +/* + * Copyright 2002-2009 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.scheduling.annotation; + +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.junit.Test; + +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.support.StaticApplicationContext; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +/** + * @author Mark Fisher + */ +public class AsyncAnnotationBeanPostProcessorTests { + + @Test + public void proxyCreated() { + StaticApplicationContext context = new StaticApplicationContext(); + BeanDefinition processorDefinition = new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class); + BeanDefinition targetDefinition = new RootBeanDefinition(AsyncAnnotationBeanPostProcessorTests.TestBean.class); + context.registerBeanDefinition("postProcessor", processorDefinition); + context.registerBeanDefinition("target", targetDefinition); + context.refresh(); + Object target = context.getBean("target"); + assertTrue(AopUtils.isAopProxy(target)); + } + + @Test + public void invokedAsynchronously() { + StaticApplicationContext context = new StaticApplicationContext(); + BeanDefinition processorDefinition = new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class); + BeanDefinition targetDefinition = new RootBeanDefinition(AsyncAnnotationBeanPostProcessorTests.TestBean.class); + context.registerBeanDefinition("postProcessor", processorDefinition); + context.registerBeanDefinition("target", targetDefinition); + context.refresh(); + ITestBean testBean = (ITestBean) context.getBean("target"); + testBean.test(); + Thread mainThread = Thread.currentThread(); + testBean.await(1000); + Thread asyncThread = testBean.getThread(); + assertNotSame(mainThread, asyncThread); + } + + @Test + public void threadNamePrefix() { + StaticApplicationContext context = new StaticApplicationContext(); + BeanDefinition processorDefinition = new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class); + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setThreadNamePrefix("testExecutor"); + executor.afterPropertiesSet(); + processorDefinition.getPropertyValues().addPropertyValue("executor", executor); + BeanDefinition targetDefinition = new RootBeanDefinition(AsyncAnnotationBeanPostProcessorTests.TestBean.class); + context.registerBeanDefinition("postProcessor", processorDefinition); + context.registerBeanDefinition("target", targetDefinition); + context.refresh(); + ITestBean testBean = (ITestBean) context.getBean("target"); + testBean.test(); + testBean.await(1000); + Thread asyncThread = testBean.getThread(); + assertTrue(asyncThread.getName().startsWith("testExecutor")); + } + + + private static interface ITestBean { + + Thread getThread(); + + void test(); + + void await(long timeout); + } + + + private static class TestBean implements ITestBean { + + private Thread thread; + + private CountDownLatch latch; + + public Thread getThread() { + return this.thread; + } + + @Async + public void test() { + this.thread = Thread.currentThread(); + this.latch.countDown(); + } + + public void await(long timeout) { + try { + this.latch.await(timeout, TimeUnit.MILLISECONDS); + } + catch (Exception e) { + Thread.currentThread().interrupt(); + } + } + } + +}