1/* 2 * Copyright 2002-2012 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package org.springframework.scheduling.aspectj; 18 19import java.util.concurrent.Callable; 20import java.util.concurrent.Executor; 21import java.util.concurrent.Future; 22 23import org.aspectj.lang.reflect.MethodSignature; 24 25import org.springframework.aop.interceptor.AsyncExecutionAspectSupport; 26import org.springframework.core.task.AsyncTaskExecutor; 27 28/** 29 * Abstract aspect that routes selected methods asynchronously. 30 * 31 * <p>This aspect needs to be injected with an implementation of 32 * {@link Executor} to activate it for a specific thread pool. 33 * Otherwise it will simply delegate all calls synchronously. 34 * 35 * @author Ramnivas Laddad 36 * @author Juergen Hoeller 37 * @author Chris Beams 38 * @since 3.0.5 39 */ 40public abstract aspect AbstractAsyncExecutionAspect extends AsyncExecutionAspectSupport { 41 42 /** 43 * Create an {@code AnnotationAsyncExecutionAspect} with a {@code null} default 44 * executor, which should instead be set via {@code #aspectOf} and 45 * {@link #setExecutor(Executor)}. 46 */ 47 public AbstractAsyncExecutionAspect() { 48 super(null); 49 } 50 51 /** 52 * Apply around advice to methods matching the {@link #asyncMethod()} pointcut, 53 * submit the actual calling of the method to the correct task executor and return 54 * immediately to the caller. 55 * @return {@link Future} if the original method returns {@code Future}; {@code null} 56 * otherwise. 57 */ 58 Object around() : asyncMethod() { 59 MethodSignature methodSignature = (MethodSignature) thisJoinPointStaticPart.getSignature(); 60 AsyncTaskExecutor executor = determineAsyncExecutor(methodSignature.getMethod()); 61 if (executor == null) { 62 return proceed(); 63 } 64 Callable<Object> callable = new Callable<Object>() { 65 public Object call() throws Exception { 66 Object result = proceed(); 67 if (result instanceof Future) { 68 return ((Future<?>) result).get(); 69 } 70 return null; 71 }}; 72 Future<?> result = executor.submit(callable); 73 if (Future.class.isAssignableFrom(methodSignature.getReturnType())) { 74 return result; 75 } 76 else { 77 return null; 78 } 79 } 80 81 /** 82 * Return the set of joinpoints at which async advice should be applied. 83 */ 84 public abstract pointcut asyncMethod(); 85 86} 87