Browse Source
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@3752 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/head
3 changed files with 130 additions and 93 deletions
@ -1,58 +0,0 @@ |
|||||||
package org.springframework.scheduling; |
|
||||||
|
|
||||||
import java.util.concurrent.Callable; |
|
||||||
import java.util.concurrent.Executor; |
|
||||||
import java.util.concurrent.Future; |
|
||||||
|
|
||||||
import org.aspectj.lang.reflect.MethodSignature; |
|
||||||
import org.springframework.core.task.AsyncTaskExecutor; |
|
||||||
import org.springframework.core.task.SimpleAsyncTaskExecutor; |
|
||||||
import org.springframework.core.task.support.TaskExecutorAdapter; |
|
||||||
|
|
||||||
/** |
|
||||||
* Abstract aspect that routes selected methods asynchronously. |
|
||||||
* <p> |
|
||||||
* This aspect, by default, uses {@link SimpleAsyncTaskExecutor} to route method |
|
||||||
* execution. However, you may inject it with any implementation of |
|
||||||
* {@link Executor} to override the default. |
|
||||||
* |
|
||||||
* @author Ramnivas Laddad |
|
||||||
*/ |
|
||||||
public abstract aspect AbstractAsynchronousExecutionAspect { |
|
||||||
private AsyncTaskExecutor asyncExecutor; |
|
||||||
|
|
||||||
public AbstractAsynchronousExecutionAspect() { |
|
||||||
// Set default executor, which may be replaced by calling setExecutor(Executor) |
|
||||||
setExecutor(new SimpleAsyncTaskExecutor()); |
|
||||||
} |
|
||||||
|
|
||||||
public abstract pointcut asyncMethod(); |
|
||||||
|
|
||||||
Object around() : asyncMethod() { |
|
||||||
Callable<Object> callable = new Callable<Object>() { |
|
||||||
public Object call() throws Exception { |
|
||||||
Object result = proceed(); |
|
||||||
if (result instanceof Future) { |
|
||||||
return ((Future<?>) result).get(); |
|
||||||
} |
|
||||||
return null; |
|
||||||
}}; |
|
||||||
|
|
||||||
Future<?> result = asyncExecutor.submit(callable); |
|
||||||
|
|
||||||
if (Future.class.isAssignableFrom(((MethodSignature)thisJoinPointStaticPart.getSignature()).getReturnType())) { |
|
||||||
return result; |
|
||||||
} else { |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void setExecutor(Executor executor) { |
|
||||||
if (executor instanceof AsyncTaskExecutor) { |
|
||||||
this.asyncExecutor = (AsyncTaskExecutor) executor; |
|
||||||
} else { |
|
||||||
this.asyncExecutor = new TaskExecutorAdapter(asyncExecutor); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -0,0 +1,76 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2010 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.aspectj; |
||||||
|
|
||||||
|
import java.util.concurrent.Callable; |
||||||
|
import java.util.concurrent.Executor; |
||||||
|
import java.util.concurrent.Future; |
||||||
|
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature; |
||||||
|
import org.springframework.core.task.AsyncTaskExecutor; |
||||||
|
import org.springframework.core.task.SimpleAsyncTaskExecutor; |
||||||
|
import org.springframework.core.task.support.TaskExecutorAdapter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Abstract aspect that routes selected methods asynchronously. |
||||||
|
* |
||||||
|
* <p>This aspect, by default, uses {@link SimpleAsyncTaskExecutor} to route |
||||||
|
* method execution. However, you may inject it with any implementation of |
||||||
|
* {@link Executor} to override the default. |
||||||
|
* |
||||||
|
* @author Ramnivas Laddad |
||||||
|
* @since 3.0.5 |
||||||
|
*/ |
||||||
|
public abstract aspect AbstractAsynchronousExecutionAspect { |
||||||
|
|
||||||
|
private AsyncTaskExecutor asyncExecutor; |
||||||
|
|
||||||
|
public AbstractAsynchronousExecutionAspect() { |
||||||
|
// Set default executor, which may be replaced by calling setExecutor. |
||||||
|
setExecutor(new SimpleAsyncTaskExecutor()); |
||||||
|
} |
||||||
|
|
||||||
|
public void setExecutor(Executor executor) { |
||||||
|
if (executor instanceof AsyncTaskExecutor) { |
||||||
|
this.asyncExecutor = (AsyncTaskExecutor) executor; |
||||||
|
} |
||||||
|
else { |
||||||
|
this.asyncExecutor = new TaskExecutorAdapter(asyncExecutor); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Object around() : asyncMethod() { |
||||||
|
Callable<Object> callable = new Callable<Object>() { |
||||||
|
public Object call() throws Exception { |
||||||
|
Object result = proceed(); |
||||||
|
if (result instanceof Future) { |
||||||
|
return ((Future<?>) result).get(); |
||||||
|
} |
||||||
|
return null; |
||||||
|
}}; |
||||||
|
Future<?> result = asyncExecutor.submit(callable); |
||||||
|
if (Future.class.isAssignableFrom(((MethodSignature) thisJoinPointStaticPart.getSignature()).getReturnType())) { |
||||||
|
return result; |
||||||
|
} |
||||||
|
else { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public abstract pointcut asyncMethod(); |
||||||
|
|
||||||
|
} |
||||||
@ -1,35 +1,54 @@ |
|||||||
package org.springframework.scheduling; |
/* |
||||||
|
* Copyright 2002-2010 the original author or authors. |
||||||
import java.util.concurrent.Future; |
* |
||||||
import org.springframework.scheduling.annotation.Async; |
* 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 |
||||||
* Aspect to route methods based on the {@link Async} annotation. |
* |
||||||
* <p> |
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
* This aspect routes methods marked with the {@link Async} annotation |
* |
||||||
* as well as methods in classes marked with the same. Any method expected |
* Unless required by applicable law or agreed to in writing, software |
||||||
* to be routed asynchronously must return either void, {@link Future}, |
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
* or a subtype of {@link Future}. This aspect, therefore, will produce |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
* a compile-time error for methods that violate this constraint on the return type. |
* See the License for the specific language governing permissions and |
||||||
* If, however, a class marked with <code>@Async</code> contains a method that |
* limitations under the License. |
||||||
* violates this constraint, it produces only a warning. |
*/ |
||||||
* |
|
||||||
* @author Ramnivas Laddad |
package org.springframework.scheduling.aspectj; |
||||||
* |
|
||||||
*/ |
import java.util.concurrent.Future; |
||||||
public aspect AnnotationDrivenAsynchronousExecutionAspect extends AbstractAsynchronousExecutionAspect { |
import org.springframework.scheduling.annotation.Async; |
||||||
private pointcut asyncMarkedMethod() |
|
||||||
: execution(@Async (void || Future+) *(..)); |
/** |
||||||
private pointcut asyncTypeMarkedMethod() |
* Aspect to route methods based on the {@link Async} annotation. |
||||||
: execution((void || Future+) (@Async *).*(..)); |
* |
||||||
|
* <p>This aspect routes methods marked with the {@link Async} annotation |
||||||
public pointcut asyncMethod() : asyncMarkedMethod() || asyncTypeMarkedMethod(); |
* as well as methods in classes marked with the same. Any method expected |
||||||
|
* to be routed asynchronously must return either void, {@link Future}, |
||||||
declare error: |
* or a subtype of {@link Future}. This aspect, therefore, will produce |
||||||
execution(@Async !(void||Future) *(..)): |
* a compile-time error for methods that violate this constraint on the return type. |
||||||
"Only method that return void or Future may have @Async annotation"; |
* If, however, a class marked with <code>@Async</code> contains a method that |
||||||
|
* violates this constraint, it produces only a warning. |
||||||
declare warning: |
* |
||||||
execution(!(void||Future) (@Async *).*(..)): |
* @author Ramnivas Laddad |
||||||
"Method in class marked with @Async that do not return void or Future will be routed synchronously"; |
* @since 3.0.5 |
||||||
} |
*/ |
||||||
|
public aspect AnnotationDrivenAsynchronousExecutionAspect extends AbstractAsynchronousExecutionAspect { |
||||||
|
|
||||||
|
private pointcut asyncMarkedMethod() |
||||||
|
: execution(@Async (void || Future+) *(..)); |
||||||
|
|
||||||
|
private pointcut asyncTypeMarkedMethod() |
||||||
|
: execution((void || Future+) (@Async *).*(..)); |
||||||
|
|
||||||
|
public pointcut asyncMethod() : asyncMarkedMethod() || asyncTypeMarkedMethod(); |
||||||
|
|
||||||
|
declare error: |
||||||
|
execution(@Async !(void||Future) *(..)): |
||||||
|
"Only methods that return void or Future may have an @Async annotation"; |
||||||
|
|
||||||
|
declare warning: |
||||||
|
execution(!(void||Future) (@Async *).*(..)): |
||||||
|
"Methods in a class marked with @Async that do not return void or Future will be routed synchronously"; |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue